From 261b53604162dd0ff361f3231b3e04646561e86b Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Sat, 14 Mar 2026 13:28:46 +0100 Subject: [PATCH] feat: multi-user system, bug fixes, security & performance fixes, and more --- kernel/src/Api/Heap.hpp | 8 + kernel/src/Api/Syscall.cpp | 76 +- kernel/src/Api/WinServer.cpp | 6 +- kernel/src/Fs/Ramdisk.cpp | 67 + kernel/src/Fs/Ramdisk.hpp | 2 + kernel/src/Main.cpp | 4 +- kernel/src/Memory/PageFrameAllocator.cpp | 1 + kernel/src/Net/Dns.cpp | 4 +- kernel/src/Net/Ipv4.cpp | 2 +- kernel/src/Sched/Scheduler.cpp | 29 +- programs/GNUmakefile | 30 +- programs/include/gui/desktop.hpp | 25 + programs/include/http/http.hpp | 316 + programs/include/montauk/config.h | 122 +- programs/include/montauk/heap.h | 4 + programs/include/montauk/string.h | 1 + programs/include/montauk/user.h | 338 + programs/lib/libc/libc.c | 38 +- programs/lib/libc/obj/libc.o | Bin 103296 -> 105256 bytes programs/man/intro.1 | 3 +- programs/src/desktop/Makefile | 5 +- programs/src/desktop/apps/app_filemanager.cpp | 7 +- programs/src/desktop/apps/app_settings.cpp | 809 +- programs/src/desktop/compose.cpp | 155 + programs/src/desktop/desktop_internal.hpp | 4 + programs/src/desktop/input.cpp | 258 +- programs/src/desktop/main.cpp | 133 +- programs/src/desktop/panel.cpp | 252 +- programs/src/httpd/main.cpp | 50 +- programs/src/init/main.cpp | 11 +- programs/src/login/Makefile | 94 + programs/src/login/font_data.cpp | 783 + programs/src/login/main.cpp | 790 + programs/src/login/stb_truetype_impl.cpp | 35 + programs/src/music/main.cpp | 21 +- programs/src/shell/Makefile | 89 + programs/src/shell/builtins.cpp | 275 + programs/src/shell/exec.cpp | 124 + programs/src/shell/main.cpp | 700 +- programs/src/shell/shell.h | 127 + programs/src/shell/vars.cpp | 166 + programs/src/whoami/main.cpp | 23 + programs/src/wikipedia/main.cpp | 8 +- scripts/copy_icons.sh | 4 + template/Makefile | 118 + template/README.md | 69 + template/docs/gui-apps.md | 916 + template/docs/syscalls.md | 572 + template/link.ld | 43 + template/src/cxxrt.cpp | 15 + template/src/main.cpp | 180 + template/src/stb_truetype_impl.cpp | 32 + template/sysroot/include/Api/Syscall.hpp | 318 + template/sysroot/include/adxintrin.h | 81 + template/sysroot/include/algorithm | 94 + template/sysroot/include/ammintrin.h | 93 + template/sysroot/include/amxbf16intrin.h | 52 + template/sysroot/include/amxcomplexintrin.h | 59 + template/sysroot/include/amxfp16intrin.h | 46 + template/sysroot/include/amxint8intrin.h | 61 + template/sysroot/include/amxtileintrin.h | 98 + template/sysroot/include/array | 519 + template/sysroot/include/atomic | 1800 ++ template/sysroot/include/avx2intrin.h | 2270 +++ template/sysroot/include/avx5124fmapsintrin.h | 216 + template/sysroot/include/avx5124vnniwintrin.h | 132 + template/sysroot/include/avx512bf16intrin.h | 163 + template/sysroot/include/avx512bf16vlintrin.h | 276 + template/sysroot/include/avx512bitalgintrin.h | 111 + .../sysroot/include/avx512bitalgvlintrin.h | 180 + template/sysroot/include/avx512bwintrin.h | 3377 ++++ template/sysroot/include/avx512cdintrin.h | 184 + template/sysroot/include/avx512dqintrin.h | 2905 +++ template/sysroot/include/avx512erintrin.h | 536 + template/sysroot/include/avx512fintrin.h | 16617 ++++++++++++++++ template/sysroot/include/avx512fp16intrin.h | 7246 +++++++ template/sysroot/include/avx512fp16vlintrin.h | 3388 ++++ template/sysroot/include/avx512ifmaintrin.h | 104 + template/sysroot/include/avx512ifmavlintrin.h | 145 + template/sysroot/include/avx512pfintrin.h | 269 + template/sysroot/include/avx512vbmi2intrin.h | 545 + .../sysroot/include/avx512vbmi2vlintrin.h | 1022 + template/sysroot/include/avx512vbmiintrin.h | 158 + template/sysroot/include/avx512vbmivlintrin.h | 273 + template/sysroot/include/avx512vlbwintrin.h | 5248 +++++ template/sysroot/include/avx512vldqintrin.h | 2016 ++ template/sysroot/include/avx512vlintrin.h | 13929 +++++++++++++ template/sysroot/include/avx512vnniintrin.h | 144 + template/sysroot/include/avx512vnnivlintrin.h | 210 + .../include/avx512vp2intersectintrin.h | 58 + .../include/avx512vp2intersectvlintrin.h | 73 + .../sysroot/include/avx512vpopcntdqintrin.h | 94 + .../sysroot/include/avx512vpopcntdqvlintrin.h | 147 + template/sysroot/include/avxifmaintrin.h | 78 + template/sysroot/include/avxintrin.h | 1607 ++ template/sysroot/include/avxneconvertintrin.h | 140 + template/sysroot/include/avxvnniint16intrin.h | 138 + template/sysroot/include/avxvnniint8intrin.h | 138 + template/sysroot/include/avxvnniintrin.h | 113 + template/sysroot/include/backward/auto_ptr.h | 343 + template/sysroot/include/backward/binders.h | 184 + template/sysroot/include/bearssl.h | 183 + template/sysroot/include/bearssl/bearssl.h | 183 + .../sysroot/include/bearssl/bearssl_aead.h | 1059 + .../sysroot/include/bearssl/bearssl_block.h | 2618 +++ template/sysroot/include/bearssl/bearssl_ec.h | 967 + .../sysroot/include/bearssl/bearssl_hash.h | 1346 ++ .../sysroot/include/bearssl/bearssl_hmac.h | 241 + .../sysroot/include/bearssl/bearssl_kdf.h | 284 + .../sysroot/include/bearssl/bearssl_pem.h | 294 + .../sysroot/include/bearssl/bearssl_prf.h | 150 + .../sysroot/include/bearssl/bearssl_rand.h | 397 + .../sysroot/include/bearssl/bearssl_rsa.h | 1655 ++ .../sysroot/include/bearssl/bearssl_ssl.h | 4296 ++++ .../sysroot/include/bearssl/bearssl_x509.h | 1474 ++ template/sysroot/include/bearssl_aead.h | 1059 + template/sysroot/include/bearssl_block.h | 2618 +++ template/sysroot/include/bearssl_ec.h | 967 + template/sysroot/include/bearssl_hash.h | 1346 ++ template/sysroot/include/bearssl_hmac.h | 241 + template/sysroot/include/bearssl_kdf.h | 284 + template/sysroot/include/bearssl_pem.h | 294 + template/sysroot/include/bearssl_prf.h | 150 + template/sysroot/include/bearssl_rand.h | 397 + template/sysroot/include/bearssl_rsa.h | 1655 ++ template/sysroot/include/bearssl_ssl.h | 4296 ++++ template/sysroot/include/bearssl_x509.h | 1474 ++ template/sysroot/include/bit | 486 + template/sysroot/include/bits/algorithmfwd.h | 970 + template/sysroot/include/bits/align.h | 109 + template/sysroot/include/bits/alloc_traits.h | 951 + template/sysroot/include/bits/allocator.h | 295 + template/sysroot/include/bits/atomic_base.h | 2068 ++ .../include/bits/atomic_lockfree_defines.h | 66 + template/sysroot/include/bits/atomic_word.h | 40 + template/sysroot/include/bits/basic_file.h | 148 + .../include/bits/boost_concept_check.h | 883 + template/sysroot/include/bits/c++0x_warning.h | 37 + template/sysroot/include/bits/c++allocator.h | 64 + template/sysroot/include/bits/c++config.h | 1836 ++ template/sysroot/include/bits/c++io.h | 57 + template/sysroot/include/bits/c++locale.h | 92 + template/sysroot/include/bits/char_traits.h | 1017 + template/sysroot/include/bits/concept_check.h | 81 + .../sysroot/include/bits/cpp_type_traits.h | 614 + template/sysroot/include/bits/cpu_defines.h | 33 + template/sysroot/include/bits/ctype_base.h | 59 + template/sysroot/include/bits/ctype_inline.h | 173 + template/sysroot/include/bits/cxxabi_forced.h | 60 + .../include/bits/cxxabi_init_exception.h | 81 + template/sysroot/include/bits/cxxabi_tweaks.h | 59 + template/sysroot/include/bits/elements_of.h | 72 + .../include/bits/enable_special_members.h | 316 + .../sysroot/include/bits/error_constants.h | 180 + template/sysroot/include/bits/exception.h | 83 + .../sysroot/include/bits/exception_defines.h | 45 + template/sysroot/include/bits/exception_ptr.h | 295 + template/sysroot/include/bits/extc++.h | 86 + template/sysroot/include/bits/functexcept.h | 143 + .../sysroot/include/bits/functional_hash.h | 305 + template/sysroot/include/bits/gthr-default.h | 298 + template/sysroot/include/bits/gthr-posix.h | 950 + template/sysroot/include/bits/gthr-single.h | 298 + template/sysroot/include/bits/gthr.h | 163 + template/sysroot/include/bits/hash_bytes.h | 59 + template/sysroot/include/bits/invoke.h | 160 + .../sysroot/include/bits/iterator_concepts.h | 1021 + template/sysroot/include/bits/max_size_type.h | 823 + template/sysroot/include/bits/memoryfwd.h | 84 + .../sysroot/include/bits/messages_members.h | 92 + template/sysroot/include/bits/move.h | 248 + .../sysroot/include/bits/nested_exception.h | 243 + template/sysroot/include/bits/opt_random.h | 221 + template/sysroot/include/bits/os_defines.h | 41 + template/sysroot/include/bits/out_ptr.h | 473 + template/sysroot/include/bits/parse_numbers.h | 295 + .../sysroot/include/bits/predefined_ops.h | 407 + template/sysroot/include/bits/ptr_traits.h | 262 + template/sysroot/include/bits/range_access.h | 370 + template/sysroot/include/bits/ranges_algo.h | 4051 ++++ .../sysroot/include/bits/ranges_algobase.h | 601 + template/sysroot/include/bits/ranges_base.h | 1071 + template/sysroot/include/bits/ranges_cmp.h | 179 + .../include/bits/ranges_uninitialized.h | 574 + template/sysroot/include/bits/ranges_util.h | 823 + template/sysroot/include/bits/refwrap.h | 462 + template/sysroot/include/bits/sat_arith.h | 148 + template/sysroot/include/bits/stdc++.h | 239 + template/sysroot/include/bits/stdtr1c++.h | 53 + template/sysroot/include/bits/stl_algo.h | 5854 ++++++ template/sysroot/include/bits/stl_algobase.h | 2352 +++ template/sysroot/include/bits/stl_construct.h | 267 + template/sysroot/include/bits/stl_function.h | 1438 ++ template/sysroot/include/bits/stl_heap.h | 584 + template/sysroot/include/bits/stl_iterator.h | 3015 +++ .../include/bits/stl_iterator_base_funcs.h | 259 + .../include/bits/stl_iterator_base_types.h | 272 + template/sysroot/include/bits/stl_numeric.h | 411 + template/sysroot/include/bits/stl_pair.h | 1335 ++ .../include/bits/stl_raw_storage_iter.h | 128 + template/sysroot/include/bits/stl_relops.h | 134 + .../sysroot/include/bits/stl_uninitialized.h | 1158 ++ template/sysroot/include/bits/string_view.tcc | 241 + .../sysroot/include/bits/text_encoding-data.h | 931 + template/sysroot/include/bits/time_members.h | 92 + template/sysroot/include/bits/unicode-data.h | 476 + template/sysroot/include/bits/unicode.h | 1132 ++ .../sysroot/include/bits/uniform_int_dist.h | 468 + template/sysroot/include/bits/unique_ptr.h | 1183 ++ .../sysroot/include/bits/uses_allocator.h | 202 + .../include/bits/uses_allocator_args.h | 248 + template/sysroot/include/bits/utility.h | 287 + template/sysroot/include/bits/version.h | 2006 ++ template/sysroot/include/bitset | 1746 ++ template/sysroot/include/bmi2intrin.h | 109 + template/sysroot/include/bmiintrin.h | 202 + template/sysroot/include/bmmintrin.h | 29 + template/sysroot/include/cet.h | 93 + template/sysroot/include/cetintrin.h | 129 + template/sysroot/include/cfloat | 56 + template/sysroot/include/cldemoteintrin.h | 47 + template/sysroot/include/clflushoptintrin.h | 49 + template/sysroot/include/climits | 59 + template/sysroot/include/clwbintrin.h | 49 + template/sysroot/include/clzerointrin.h | 44 + template/sysroot/include/cmpccxaddintrin.h | 89 + template/sysroot/include/compare | 1258 ++ template/sysroot/include/concepts | 389 + template/sysroot/include/coroutine | 361 + template/sysroot/include/cpuid.h | 362 + template/sysroot/include/cross-stdarg.h | 72 + template/sysroot/include/cstdalign | 44 + template/sysroot/include/cstdarg | 58 + template/sysroot/include/cstdbool | 44 + template/sysroot/include/cstddef | 192 + template/sysroot/include/cstdint | 146 + template/sysroot/include/cstdlib | 279 + template/sysroot/include/cxxabi.h | 715 + template/sysroot/include/debug/assertions.h | 68 + template/sysroot/include/debug/debug.h | 145 + template/sysroot/include/emmintrin.h | 1608 ++ template/sysroot/include/enqcmdintrin.h | 55 + template/sysroot/include/exception | 170 + template/sysroot/include/expected | 1852 ++ template/sysroot/include/ext/aligned_buffer.h | 128 + template/sysroot/include/ext/alloc_traits.h | 185 + template/sysroot/include/ext/atomicity.h | 127 + template/sysroot/include/ext/cast.h | 121 + template/sysroot/include/ext/concurrence.h | 315 + template/sysroot/include/ext/iterator | 116 + template/sysroot/include/ext/numeric_traits.h | 241 + template/sysroot/include/ext/pointer.h | 611 + template/sysroot/include/ext/type_traits.h | 273 + template/sysroot/include/ext/typelist.h | 538 + template/sysroot/include/f16cintrin.h | 98 + template/sysroot/include/float.h | 631 + template/sysroot/include/fma4intrin.h | 241 + template/sysroot/include/fmaintrin.h | 302 + template/sysroot/include/functional | 1505 ++ template/sysroot/include/fxsrintrin.h | 73 + template/sysroot/include/gcov.h | 70 + template/sysroot/include/generator | 821 + template/sysroot/include/gfniintrin.h | 430 + template/sysroot/include/gui/canvas.hpp | 251 + template/sysroot/include/gui/desktop.hpp | 161 + template/sysroot/include/gui/draw.hpp | 394 + template/sysroot/include/gui/font.hpp | 99 + template/sysroot/include/gui/framebuffer.hpp | 196 + template/sysroot/include/gui/gui.hpp | 94 + template/sysroot/include/gui/stb_image.h | 7988 ++++++++ template/sysroot/include/gui/stb_math.h | 95 + template/sysroot/include/gui/stb_truetype.h | 5084 +++++ template/sysroot/include/gui/svg.hpp | 1521 ++ template/sysroot/include/gui/terminal.hpp | 688 + template/sysroot/include/gui/truetype.hpp | 409 + template/sysroot/include/gui/widgets.hpp | 359 + template/sysroot/include/gui/window.hpp | 96 + template/sysroot/include/hresetintrin.h | 48 + template/sysroot/include/http/http.hpp | 316 + template/sysroot/include/ia32intrin.h | 317 + template/sysroot/include/immintrin.h | 149 + template/sysroot/include/initializer_list | 105 + template/sysroot/include/iso646.h | 45 + template/sysroot/include/iterator | 84 + template/sysroot/include/keylockerintrin.h | 129 + template/sysroot/include/libc/assert.h | 23 + template/sysroot/include/libc/ctype.h | 28 + template/sysroot/include/libc/errno.h | 29 + template/sysroot/include/libc/fcntl.h | 22 + template/sysroot/include/libc/inttypes.h | 27 + template/sysroot/include/libc/limits.h | 31 + template/sysroot/include/libc/math.h | 31 + template/sysroot/include/libc/stdio.h | 77 + template/sysroot/include/libc/stdlib.h | 66 + template/sysroot/include/libc/string.h | 36 + template/sysroot/include/libc/strings.h | 17 + template/sysroot/include/libc/sys/stat.h | 24 + template/sysroot/include/libc/sys/time.h | 24 + template/sysroot/include/libc/sys/types.h | 23 + template/sysroot/include/libc/unistd.h | 20 + template/sysroot/include/limits | 2240 +++ template/sysroot/include/limits.h | 184 + template/sysroot/include/lwpintrin.h | 107 + template/sysroot/include/lzcntintrin.h | 75 + template/sysroot/include/memory | 175 + template/sysroot/include/mm3dnow.h | 233 + template/sysroot/include/mm_malloc.h | 78 + template/sysroot/include/mmintrin.h | 965 + template/sysroot/include/montauk/config.h | 429 + template/sysroot/include/montauk/heap.h | 246 + template/sysroot/include/montauk/string.h | 108 + template/sysroot/include/montauk/syscall.h | 432 + template/sysroot/include/montauk/toml.h | 573 + template/sysroot/include/montauk/user.h | 338 + template/sysroot/include/movdirintrin.h | 74 + template/sysroot/include/mwaitintrin.h | 52 + template/sysroot/include/mwaitxintrin.h | 50 + template/sysroot/include/new | 238 + template/sysroot/include/nmmintrin.h | 33 + template/sysroot/include/numbers | 236 + template/sysroot/include/numeric | 744 + template/sysroot/include/optional | 1522 ++ template/sysroot/include/pconfigintrin.h | 78 + template/sysroot/include/pkuintrin.h | 56 + template/sysroot/include/pmmintrin.h | 121 + template/sysroot/include/popcntintrin.h | 53 + template/sysroot/include/prfchiintrin.h | 61 + template/sysroot/include/prfchwintrin.h | 37 + template/sysroot/include/ranges | 9521 +++++++++ template/sysroot/include/raointintrin.h | 100 + template/sysroot/include/ratio | 651 + template/sysroot/include/rdseedintrin.h | 66 + template/sysroot/include/rtmintrin.h | 84 + template/sysroot/include/scoped_allocator | 528 + template/sysroot/include/serializeintrin.h | 49 + template/sysroot/include/sgxintrin.h | 253 + template/sysroot/include/sha512intrin.h | 64 + template/sysroot/include/shaintrin.h | 98 + template/sysroot/include/sm3intrin.h | 72 + template/sysroot/include/sm4intrin.h | 70 + template/sysroot/include/smmintrin.h | 852 + template/sysroot/include/source_location | 93 + template/sysroot/include/span | 512 + template/sysroot/include/stdalign.h | 40 + template/sysroot/include/stdarg.h | 135 + template/sysroot/include/stdatomic.h | 255 + template/sysroot/include/stdbool.h | 51 + template/sysroot/include/stdckdint.h | 40 + template/sysroot/include/stddef.h | 463 + template/sysroot/include/stdfix.h | 204 + template/sysroot/include/stdint-gcc.h | 402 + template/sysroot/include/stdint.h | 14 + template/sysroot/include/stdnoreturn.h | 35 + template/sysroot/include/string_view | 908 + template/sysroot/include/syslimits.h | 8 + template/sysroot/include/tbmintrin.h | 180 + template/sysroot/include/tgmath.h | 127 + template/sysroot/include/tls/tls.hpp | 45 + template/sysroot/include/tmmintrin.h | 249 + template/sysroot/include/tsxldtrkintrin.h | 56 + template/sysroot/include/tuple | 3035 +++ template/sysroot/include/type_traits | 4007 ++++ template/sysroot/include/typeindex | 129 + template/sysroot/include/typeinfo | 254 + template/sysroot/include/uintrintrin.h | 84 + template/sysroot/include/unwind.h | 298 + template/sysroot/include/usermsrintrin.h | 60 + template/sysroot/include/utility | 235 + template/sysroot/include/vaesintrin.h | 111 + template/sysroot/include/varargs.h | 7 + template/sysroot/include/variant | 1970 ++ template/sysroot/include/version | 38 + template/sysroot/include/vpclmulqdqintrin.h | 81 + template/sysroot/include/waitpkgintrin.h | 63 + template/sysroot/include/wbnoinvdintrin.h | 49 + template/sysroot/include/wmmintrin.h | 119 + template/sysroot/include/x86gprintrin.h | 277 + template/sysroot/include/x86intrin.h | 42 + template/sysroot/include/xmmintrin.h | 1340 ++ template/sysroot/include/xopintrin.h | 850 + template/sysroot/include/xsavecintrin.h | 58 + template/sysroot/include/xsaveintrin.h | 86 + template/sysroot/include/xsaveoptintrin.h | 58 + template/sysroot/include/xsavesintrin.h | 72 + template/sysroot/include/xtestintrin.h | 51 + template/sysroot/lib/libbearssl.a | Bin 0 -> 958944 bytes template/sysroot/lib/libjpeg.a | Bin 0 -> 330158 bytes template/sysroot/lib/liblibc.a | Bin 0 -> 105990 bytes template/sysroot/lib/libtls.a | Bin 0 -> 106682 bytes 389 files changed, 231853 insertions(+), 591 deletions(-) create mode 100644 programs/include/http/http.hpp create mode 100644 programs/include/montauk/user.h create mode 100644 programs/src/login/Makefile create mode 100644 programs/src/login/font_data.cpp create mode 100644 programs/src/login/main.cpp create mode 100644 programs/src/login/stb_truetype_impl.cpp create mode 100644 programs/src/shell/Makefile create mode 100644 programs/src/shell/builtins.cpp create mode 100644 programs/src/shell/exec.cpp create mode 100644 programs/src/shell/shell.h create mode 100644 programs/src/shell/vars.cpp create mode 100644 programs/src/whoami/main.cpp create mode 100644 template/Makefile create mode 100644 template/README.md create mode 100644 template/docs/gui-apps.md create mode 100644 template/docs/syscalls.md create mode 100644 template/link.ld create mode 100644 template/src/cxxrt.cpp create mode 100644 template/src/main.cpp create mode 100644 template/src/stb_truetype_impl.cpp create mode 100644 template/sysroot/include/Api/Syscall.hpp create mode 100644 template/sysroot/include/adxintrin.h create mode 100644 template/sysroot/include/algorithm create mode 100644 template/sysroot/include/ammintrin.h create mode 100644 template/sysroot/include/amxbf16intrin.h create mode 100644 template/sysroot/include/amxcomplexintrin.h create mode 100644 template/sysroot/include/amxfp16intrin.h create mode 100644 template/sysroot/include/amxint8intrin.h create mode 100644 template/sysroot/include/amxtileintrin.h create mode 100644 template/sysroot/include/array create mode 100644 template/sysroot/include/atomic create mode 100644 template/sysroot/include/avx2intrin.h create mode 100644 template/sysroot/include/avx5124fmapsintrin.h create mode 100644 template/sysroot/include/avx5124vnniwintrin.h create mode 100644 template/sysroot/include/avx512bf16intrin.h create mode 100644 template/sysroot/include/avx512bf16vlintrin.h create mode 100644 template/sysroot/include/avx512bitalgintrin.h create mode 100644 template/sysroot/include/avx512bitalgvlintrin.h create mode 100644 template/sysroot/include/avx512bwintrin.h create mode 100644 template/sysroot/include/avx512cdintrin.h create mode 100644 template/sysroot/include/avx512dqintrin.h create mode 100644 template/sysroot/include/avx512erintrin.h create mode 100644 template/sysroot/include/avx512fintrin.h create mode 100644 template/sysroot/include/avx512fp16intrin.h create mode 100644 template/sysroot/include/avx512fp16vlintrin.h create mode 100644 template/sysroot/include/avx512ifmaintrin.h create mode 100644 template/sysroot/include/avx512ifmavlintrin.h create mode 100644 template/sysroot/include/avx512pfintrin.h create mode 100644 template/sysroot/include/avx512vbmi2intrin.h create mode 100644 template/sysroot/include/avx512vbmi2vlintrin.h create mode 100644 template/sysroot/include/avx512vbmiintrin.h create mode 100644 template/sysroot/include/avx512vbmivlintrin.h create mode 100644 template/sysroot/include/avx512vlbwintrin.h create mode 100644 template/sysroot/include/avx512vldqintrin.h create mode 100644 template/sysroot/include/avx512vlintrin.h create mode 100644 template/sysroot/include/avx512vnniintrin.h create mode 100644 template/sysroot/include/avx512vnnivlintrin.h create mode 100644 template/sysroot/include/avx512vp2intersectintrin.h create mode 100644 template/sysroot/include/avx512vp2intersectvlintrin.h create mode 100644 template/sysroot/include/avx512vpopcntdqintrin.h create mode 100644 template/sysroot/include/avx512vpopcntdqvlintrin.h create mode 100644 template/sysroot/include/avxifmaintrin.h create mode 100644 template/sysroot/include/avxintrin.h create mode 100644 template/sysroot/include/avxneconvertintrin.h create mode 100644 template/sysroot/include/avxvnniint16intrin.h create mode 100644 template/sysroot/include/avxvnniint8intrin.h create mode 100644 template/sysroot/include/avxvnniintrin.h create mode 100644 template/sysroot/include/backward/auto_ptr.h create mode 100644 template/sysroot/include/backward/binders.h create mode 100644 template/sysroot/include/bearssl.h create mode 100644 template/sysroot/include/bearssl/bearssl.h create mode 100644 template/sysroot/include/bearssl/bearssl_aead.h create mode 100644 template/sysroot/include/bearssl/bearssl_block.h create mode 100644 template/sysroot/include/bearssl/bearssl_ec.h create mode 100644 template/sysroot/include/bearssl/bearssl_hash.h create mode 100644 template/sysroot/include/bearssl/bearssl_hmac.h create mode 100644 template/sysroot/include/bearssl/bearssl_kdf.h create mode 100644 template/sysroot/include/bearssl/bearssl_pem.h create mode 100644 template/sysroot/include/bearssl/bearssl_prf.h create mode 100644 template/sysroot/include/bearssl/bearssl_rand.h create mode 100644 template/sysroot/include/bearssl/bearssl_rsa.h create mode 100644 template/sysroot/include/bearssl/bearssl_ssl.h create mode 100644 template/sysroot/include/bearssl/bearssl_x509.h create mode 100644 template/sysroot/include/bearssl_aead.h create mode 100644 template/sysroot/include/bearssl_block.h create mode 100644 template/sysroot/include/bearssl_ec.h create mode 100644 template/sysroot/include/bearssl_hash.h create mode 100644 template/sysroot/include/bearssl_hmac.h create mode 100644 template/sysroot/include/bearssl_kdf.h create mode 100644 template/sysroot/include/bearssl_pem.h create mode 100644 template/sysroot/include/bearssl_prf.h create mode 100644 template/sysroot/include/bearssl_rand.h create mode 100644 template/sysroot/include/bearssl_rsa.h create mode 100644 template/sysroot/include/bearssl_ssl.h create mode 100644 template/sysroot/include/bearssl_x509.h create mode 100644 template/sysroot/include/bit create mode 100644 template/sysroot/include/bits/algorithmfwd.h create mode 100644 template/sysroot/include/bits/align.h create mode 100644 template/sysroot/include/bits/alloc_traits.h create mode 100644 template/sysroot/include/bits/allocator.h create mode 100644 template/sysroot/include/bits/atomic_base.h create mode 100644 template/sysroot/include/bits/atomic_lockfree_defines.h create mode 100644 template/sysroot/include/bits/atomic_word.h create mode 100644 template/sysroot/include/bits/basic_file.h create mode 100644 template/sysroot/include/bits/boost_concept_check.h create mode 100644 template/sysroot/include/bits/c++0x_warning.h create mode 100644 template/sysroot/include/bits/c++allocator.h create mode 100644 template/sysroot/include/bits/c++config.h create mode 100644 template/sysroot/include/bits/c++io.h create mode 100644 template/sysroot/include/bits/c++locale.h create mode 100644 template/sysroot/include/bits/char_traits.h create mode 100644 template/sysroot/include/bits/concept_check.h create mode 100644 template/sysroot/include/bits/cpp_type_traits.h create mode 100644 template/sysroot/include/bits/cpu_defines.h create mode 100644 template/sysroot/include/bits/ctype_base.h create mode 100644 template/sysroot/include/bits/ctype_inline.h create mode 100644 template/sysroot/include/bits/cxxabi_forced.h create mode 100644 template/sysroot/include/bits/cxxabi_init_exception.h create mode 100644 template/sysroot/include/bits/cxxabi_tweaks.h create mode 100644 template/sysroot/include/bits/elements_of.h create mode 100644 template/sysroot/include/bits/enable_special_members.h create mode 100644 template/sysroot/include/bits/error_constants.h create mode 100644 template/sysroot/include/bits/exception.h create mode 100644 template/sysroot/include/bits/exception_defines.h create mode 100644 template/sysroot/include/bits/exception_ptr.h create mode 100644 template/sysroot/include/bits/extc++.h create mode 100644 template/sysroot/include/bits/functexcept.h create mode 100644 template/sysroot/include/bits/functional_hash.h create mode 100644 template/sysroot/include/bits/gthr-default.h create mode 100644 template/sysroot/include/bits/gthr-posix.h create mode 100644 template/sysroot/include/bits/gthr-single.h create mode 100644 template/sysroot/include/bits/gthr.h create mode 100644 template/sysroot/include/bits/hash_bytes.h create mode 100644 template/sysroot/include/bits/invoke.h create mode 100644 template/sysroot/include/bits/iterator_concepts.h create mode 100644 template/sysroot/include/bits/max_size_type.h create mode 100644 template/sysroot/include/bits/memoryfwd.h create mode 100644 template/sysroot/include/bits/messages_members.h create mode 100644 template/sysroot/include/bits/move.h create mode 100644 template/sysroot/include/bits/nested_exception.h create mode 100644 template/sysroot/include/bits/opt_random.h create mode 100644 template/sysroot/include/bits/os_defines.h create mode 100644 template/sysroot/include/bits/out_ptr.h create mode 100644 template/sysroot/include/bits/parse_numbers.h create mode 100644 template/sysroot/include/bits/predefined_ops.h create mode 100644 template/sysroot/include/bits/ptr_traits.h create mode 100644 template/sysroot/include/bits/range_access.h create mode 100644 template/sysroot/include/bits/ranges_algo.h create mode 100644 template/sysroot/include/bits/ranges_algobase.h create mode 100644 template/sysroot/include/bits/ranges_base.h create mode 100644 template/sysroot/include/bits/ranges_cmp.h create mode 100644 template/sysroot/include/bits/ranges_uninitialized.h create mode 100644 template/sysroot/include/bits/ranges_util.h create mode 100644 template/sysroot/include/bits/refwrap.h create mode 100644 template/sysroot/include/bits/sat_arith.h create mode 100644 template/sysroot/include/bits/stdc++.h create mode 100644 template/sysroot/include/bits/stdtr1c++.h create mode 100644 template/sysroot/include/bits/stl_algo.h create mode 100644 template/sysroot/include/bits/stl_algobase.h create mode 100644 template/sysroot/include/bits/stl_construct.h create mode 100644 template/sysroot/include/bits/stl_function.h create mode 100644 template/sysroot/include/bits/stl_heap.h create mode 100644 template/sysroot/include/bits/stl_iterator.h create mode 100644 template/sysroot/include/bits/stl_iterator_base_funcs.h create mode 100644 template/sysroot/include/bits/stl_iterator_base_types.h create mode 100644 template/sysroot/include/bits/stl_numeric.h create mode 100644 template/sysroot/include/bits/stl_pair.h create mode 100644 template/sysroot/include/bits/stl_raw_storage_iter.h create mode 100644 template/sysroot/include/bits/stl_relops.h create mode 100644 template/sysroot/include/bits/stl_uninitialized.h create mode 100644 template/sysroot/include/bits/string_view.tcc create mode 100644 template/sysroot/include/bits/text_encoding-data.h create mode 100644 template/sysroot/include/bits/time_members.h create mode 100644 template/sysroot/include/bits/unicode-data.h create mode 100644 template/sysroot/include/bits/unicode.h create mode 100644 template/sysroot/include/bits/uniform_int_dist.h create mode 100644 template/sysroot/include/bits/unique_ptr.h create mode 100644 template/sysroot/include/bits/uses_allocator.h create mode 100644 template/sysroot/include/bits/uses_allocator_args.h create mode 100644 template/sysroot/include/bits/utility.h create mode 100644 template/sysroot/include/bits/version.h create mode 100644 template/sysroot/include/bitset create mode 100644 template/sysroot/include/bmi2intrin.h create mode 100644 template/sysroot/include/bmiintrin.h create mode 100644 template/sysroot/include/bmmintrin.h create mode 100644 template/sysroot/include/cet.h create mode 100644 template/sysroot/include/cetintrin.h create mode 100644 template/sysroot/include/cfloat create mode 100644 template/sysroot/include/cldemoteintrin.h create mode 100644 template/sysroot/include/clflushoptintrin.h create mode 100644 template/sysroot/include/climits create mode 100644 template/sysroot/include/clwbintrin.h create mode 100644 template/sysroot/include/clzerointrin.h create mode 100644 template/sysroot/include/cmpccxaddintrin.h create mode 100644 template/sysroot/include/compare create mode 100644 template/sysroot/include/concepts create mode 100644 template/sysroot/include/coroutine create mode 100644 template/sysroot/include/cpuid.h create mode 100644 template/sysroot/include/cross-stdarg.h create mode 100644 template/sysroot/include/cstdalign create mode 100644 template/sysroot/include/cstdarg create mode 100644 template/sysroot/include/cstdbool create mode 100644 template/sysroot/include/cstddef create mode 100644 template/sysroot/include/cstdint create mode 100644 template/sysroot/include/cstdlib create mode 100644 template/sysroot/include/cxxabi.h create mode 100644 template/sysroot/include/debug/assertions.h create mode 100644 template/sysroot/include/debug/debug.h create mode 100644 template/sysroot/include/emmintrin.h create mode 100644 template/sysroot/include/enqcmdintrin.h create mode 100644 template/sysroot/include/exception create mode 100644 template/sysroot/include/expected create mode 100644 template/sysroot/include/ext/aligned_buffer.h create mode 100644 template/sysroot/include/ext/alloc_traits.h create mode 100644 template/sysroot/include/ext/atomicity.h create mode 100644 template/sysroot/include/ext/cast.h create mode 100644 template/sysroot/include/ext/concurrence.h create mode 100644 template/sysroot/include/ext/iterator create mode 100644 template/sysroot/include/ext/numeric_traits.h create mode 100644 template/sysroot/include/ext/pointer.h create mode 100644 template/sysroot/include/ext/type_traits.h create mode 100644 template/sysroot/include/ext/typelist.h create mode 100644 template/sysroot/include/f16cintrin.h create mode 100644 template/sysroot/include/float.h create mode 100644 template/sysroot/include/fma4intrin.h create mode 100644 template/sysroot/include/fmaintrin.h create mode 100644 template/sysroot/include/functional create mode 100644 template/sysroot/include/fxsrintrin.h create mode 100644 template/sysroot/include/gcov.h create mode 100644 template/sysroot/include/generator create mode 100644 template/sysroot/include/gfniintrin.h create mode 100644 template/sysroot/include/gui/canvas.hpp create mode 100644 template/sysroot/include/gui/desktop.hpp create mode 100644 template/sysroot/include/gui/draw.hpp create mode 100644 template/sysroot/include/gui/font.hpp create mode 100644 template/sysroot/include/gui/framebuffer.hpp create mode 100644 template/sysroot/include/gui/gui.hpp create mode 100644 template/sysroot/include/gui/stb_image.h create mode 100644 template/sysroot/include/gui/stb_math.h create mode 100644 template/sysroot/include/gui/stb_truetype.h create mode 100644 template/sysroot/include/gui/svg.hpp create mode 100644 template/sysroot/include/gui/terminal.hpp create mode 100644 template/sysroot/include/gui/truetype.hpp create mode 100644 template/sysroot/include/gui/widgets.hpp create mode 100644 template/sysroot/include/gui/window.hpp create mode 100644 template/sysroot/include/hresetintrin.h create mode 100644 template/sysroot/include/http/http.hpp create mode 100644 template/sysroot/include/ia32intrin.h create mode 100644 template/sysroot/include/immintrin.h create mode 100644 template/sysroot/include/initializer_list create mode 100644 template/sysroot/include/iso646.h create mode 100644 template/sysroot/include/iterator create mode 100644 template/sysroot/include/keylockerintrin.h create mode 100644 template/sysroot/include/libc/assert.h create mode 100644 template/sysroot/include/libc/ctype.h create mode 100644 template/sysroot/include/libc/errno.h create mode 100644 template/sysroot/include/libc/fcntl.h create mode 100644 template/sysroot/include/libc/inttypes.h create mode 100644 template/sysroot/include/libc/limits.h create mode 100644 template/sysroot/include/libc/math.h create mode 100644 template/sysroot/include/libc/stdio.h create mode 100644 template/sysroot/include/libc/stdlib.h create mode 100644 template/sysroot/include/libc/string.h create mode 100644 template/sysroot/include/libc/strings.h create mode 100644 template/sysroot/include/libc/sys/stat.h create mode 100644 template/sysroot/include/libc/sys/time.h create mode 100644 template/sysroot/include/libc/sys/types.h create mode 100644 template/sysroot/include/libc/unistd.h create mode 100644 template/sysroot/include/limits create mode 100644 template/sysroot/include/limits.h create mode 100644 template/sysroot/include/lwpintrin.h create mode 100644 template/sysroot/include/lzcntintrin.h create mode 100644 template/sysroot/include/memory create mode 100644 template/sysroot/include/mm3dnow.h create mode 100644 template/sysroot/include/mm_malloc.h create mode 100644 template/sysroot/include/mmintrin.h create mode 100644 template/sysroot/include/montauk/config.h create mode 100644 template/sysroot/include/montauk/heap.h create mode 100644 template/sysroot/include/montauk/string.h create mode 100644 template/sysroot/include/montauk/syscall.h create mode 100644 template/sysroot/include/montauk/toml.h create mode 100644 template/sysroot/include/montauk/user.h create mode 100644 template/sysroot/include/movdirintrin.h create mode 100644 template/sysroot/include/mwaitintrin.h create mode 100644 template/sysroot/include/mwaitxintrin.h create mode 100644 template/sysroot/include/new create mode 100644 template/sysroot/include/nmmintrin.h create mode 100644 template/sysroot/include/numbers create mode 100644 template/sysroot/include/numeric create mode 100644 template/sysroot/include/optional create mode 100644 template/sysroot/include/pconfigintrin.h create mode 100644 template/sysroot/include/pkuintrin.h create mode 100644 template/sysroot/include/pmmintrin.h create mode 100644 template/sysroot/include/popcntintrin.h create mode 100644 template/sysroot/include/prfchiintrin.h create mode 100644 template/sysroot/include/prfchwintrin.h create mode 100644 template/sysroot/include/ranges create mode 100644 template/sysroot/include/raointintrin.h create mode 100644 template/sysroot/include/ratio create mode 100644 template/sysroot/include/rdseedintrin.h create mode 100644 template/sysroot/include/rtmintrin.h create mode 100644 template/sysroot/include/scoped_allocator create mode 100644 template/sysroot/include/serializeintrin.h create mode 100644 template/sysroot/include/sgxintrin.h create mode 100644 template/sysroot/include/sha512intrin.h create mode 100644 template/sysroot/include/shaintrin.h create mode 100644 template/sysroot/include/sm3intrin.h create mode 100644 template/sysroot/include/sm4intrin.h create mode 100644 template/sysroot/include/smmintrin.h create mode 100644 template/sysroot/include/source_location create mode 100644 template/sysroot/include/span create mode 100644 template/sysroot/include/stdalign.h create mode 100644 template/sysroot/include/stdarg.h create mode 100644 template/sysroot/include/stdatomic.h create mode 100644 template/sysroot/include/stdbool.h create mode 100644 template/sysroot/include/stdckdint.h create mode 100644 template/sysroot/include/stddef.h create mode 100644 template/sysroot/include/stdfix.h create mode 100644 template/sysroot/include/stdint-gcc.h create mode 100644 template/sysroot/include/stdint.h create mode 100644 template/sysroot/include/stdnoreturn.h create mode 100644 template/sysroot/include/string_view create mode 100644 template/sysroot/include/syslimits.h create mode 100644 template/sysroot/include/tbmintrin.h create mode 100644 template/sysroot/include/tgmath.h create mode 100644 template/sysroot/include/tls/tls.hpp create mode 100644 template/sysroot/include/tmmintrin.h create mode 100644 template/sysroot/include/tsxldtrkintrin.h create mode 100644 template/sysroot/include/tuple create mode 100644 template/sysroot/include/type_traits create mode 100644 template/sysroot/include/typeindex create mode 100644 template/sysroot/include/typeinfo create mode 100644 template/sysroot/include/uintrintrin.h create mode 100644 template/sysroot/include/unwind.h create mode 100644 template/sysroot/include/usermsrintrin.h create mode 100644 template/sysroot/include/utility create mode 100644 template/sysroot/include/vaesintrin.h create mode 100644 template/sysroot/include/varargs.h create mode 100644 template/sysroot/include/variant create mode 100644 template/sysroot/include/version create mode 100644 template/sysroot/include/vpclmulqdqintrin.h create mode 100644 template/sysroot/include/waitpkgintrin.h create mode 100644 template/sysroot/include/wbnoinvdintrin.h create mode 100644 template/sysroot/include/wmmintrin.h create mode 100644 template/sysroot/include/x86gprintrin.h create mode 100644 template/sysroot/include/x86intrin.h create mode 100644 template/sysroot/include/xmmintrin.h create mode 100644 template/sysroot/include/xopintrin.h create mode 100644 template/sysroot/include/xsavecintrin.h create mode 100644 template/sysroot/include/xsaveintrin.h create mode 100644 template/sysroot/include/xsaveoptintrin.h create mode 100644 template/sysroot/include/xsavesintrin.h create mode 100644 template/sysroot/include/xtestintrin.h create mode 100644 template/sysroot/lib/libbearssl.a create mode 100644 template/sysroot/lib/libjpeg.a create mode 100644 template/sysroot/lib/liblibc.a create mode 100644 template/sysroot/lib/libtls.a diff --git a/kernel/src/Api/Heap.hpp b/kernel/src/Api/Heap.hpp index f09dbfb..8570105 100644 --- a/kernel/src/Api/Heap.hpp +++ b/kernel/src/Api/Heap.hpp @@ -36,11 +36,19 @@ namespace Montauk { auto* proc = Sched::GetCurrentProcessPtr(); if (proc == nullptr) return 0; + // Guard against overflow before rounding + static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL; + if (size > 0xFFFFFFFFFFFF0000ULL) return 0; + // Round up to page boundary size = (size + 0xFFF) & ~0xFFFULL; if (size == 0) size = 0x1000; uint64_t userVa = proc->heapNext; + + // Ensure allocation stays within user address space + if (userVa + size < userVa || userVa + size > USER_SPACE_END) return 0; + uint64_t numPages = size / 0x1000; // Allocate physical pages and map them into the process diff --git a/kernel/src/Api/Syscall.cpp b/kernel/src/Api/Syscall.cpp index 354d7bd..45da212 100644 --- a/kernel/src/Api/Syscall.cpp +++ b/kernel/src/Api/Syscall.cpp @@ -38,6 +38,23 @@ extern "C" void SyscallEntry(); namespace Montauk { + // ---- User pointer validation ---- + // Reject pointers that fall in the kernel-half of the address space + // (canonical high addresses, i.e. >= 0x0000800000000000). + // This prevents userspace from tricking the kernel into reading/writing + // kernel memory via syscall arguments. + + static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL; + + static bool IsUserPtr(uint64_t addr) { + return addr == 0 || addr < USER_SPACE_END; + } + + // Validate that a pointer is non-null and in user space + static bool ValidUserPtr(uint64_t addr) { + return addr != 0 && addr < USER_SPACE_END; + } + // ---- Dispatch ---- extern "C" int64_t SyscallDispatch(SyscallFrame* frame) { @@ -59,14 +76,17 @@ namespace Montauk { case SYS_GETPID: return (int64_t)Sys_GetPid(); case SYS_PRINT: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_Print((const char*)frame->arg1); return 0; case SYS_PUTCHAR: Sys_Putchar((char)frame->arg1); return 0; case SYS_OPEN: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_Open((const char*)frame->arg1); case SYS_READ: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2, frame->arg3, frame->arg4); case SYS_GETSIZE: @@ -75,6 +95,7 @@ namespace Montauk { Sys_Close((int)frame->arg1); return 0; case SYS_READDIR: + if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_ReadDir((const char*)frame->arg1, (const char**)frame->arg2, (int)frame->arg3); @@ -88,11 +109,13 @@ namespace Montauk { case SYS_GETMILLISECONDS: return (int64_t)Sys_GetMilliseconds(); case SYS_GETINFO: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_GetInfo((SysInfo*)frame->arg1); return 0; case SYS_ISKEYAVAILABLE: return (int64_t)Sys_IsKeyAvailable(); case SYS_GETKEY: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_GetKey((KeyEvent*)frame->arg1); return 0; case SYS_GETCHAR: @@ -100,11 +123,14 @@ namespace Montauk { case SYS_PING: return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2); case SYS_SPAWN: - return (int64_t)Sys_Spawn((const char*)frame->arg1, (const char*)frame->arg2); + if (!ValidUserPtr(frame->arg1)) return -1; + return (int64_t)Sys_Spawn((const char*)frame->arg1, + IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr); case SYS_WAITPID: Sys_WaitPid((int)frame->arg1); return 0; case SYS_FBINFO: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_FbInfo((FbInfo*)frame->arg1); return 0; case SYS_FBMAP: @@ -112,6 +138,7 @@ namespace Montauk { case SYS_TERMSIZE: return (int64_t)Sys_TermSize(); case SYS_GETARGS: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2); case SYS_RESET: Sys_Reset(); @@ -120,6 +147,7 @@ namespace Montauk { Sys_Shutdown(); return 0; case SYS_GETTIME: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_GetTime((DateTime*)frame->arg1); return 0; case SYS_SOCKET: @@ -133,61 +161,83 @@ namespace Montauk { case SYS_ACCEPT: return (int64_t)Sys_Accept((int)frame->arg1); case SYS_SEND: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3); case SYS_RECV: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3); case SYS_CLOSESOCK: Sys_CloseSock((int)frame->arg1); return 0; case SYS_GETNETCFG: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_GetNetCfg((NetCfg*)frame->arg1); return 0; case SYS_SETNETCFG: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1); case SYS_SENDTO: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3, (uint32_t)frame->arg4, (uint16_t)frame->arg5); case SYS_RECVFROM: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2, - (uint32_t)frame->arg3, (uint32_t*)frame->arg4, - (uint16_t*)frame->arg5); + (uint32_t)frame->arg3, + IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr, + IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr); case SYS_FWRITE: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2, frame->arg3, frame->arg4); case SYS_FCREATE: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_FCreate((const char*)frame->arg1); case SYS_FDELETE: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_FDelete((const char*)frame->arg1); case SYS_FMKDIR: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_FMkdir((const char*)frame->arg1); case SYS_DRIVELIST: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2); case SYS_TERMSCALE: return Sys_TermScale(frame->arg1, frame->arg2); case SYS_RESOLVE: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_Resolve((const char*)frame->arg1); case SYS_GETRANDOM: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2); case SYS_KLOG: + if (!ValidUserPtr(frame->arg1)) return -1; return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2); case SYS_MOUSESTATE: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_MouseState((MouseState*)frame->arg1); return 0; case SYS_SETMOUSEBOUNDS: Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2); return 0; case SYS_SPAWN_REDIR: - return (int64_t)Sys_SpawnRedir((const char*)frame->arg1, (const char*)frame->arg2); + if (!ValidUserPtr(frame->arg1)) return -1; + return (int64_t)Sys_SpawnRedir((const char*)frame->arg1, + IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr); case SYS_CHILDIO_READ: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3); case SYS_CHILDIO_WRITE: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3); case SYS_CHILDIO_WRITEKEY: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2); case SYS_CHILDIO_SETTERMSZ: return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3); case SYS_WINCREATE: + if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg4)) return -1; return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2, (int)frame->arg3, (WinCreateResult*)frame->arg4); case SYS_WINDESTROY: @@ -195,16 +245,20 @@ namespace Montauk { case SYS_WINPRESENT: return (int64_t)Sys_WinPresent((int)frame->arg1); case SYS_WINPOLL: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2); case SYS_WINENUM: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2); case SYS_WINMAP: return (int64_t)Sys_WinMap((int)frame->arg1); case SYS_WINSENDEVENT: + if (!ValidUserPtr(frame->arg2)) return -1; return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2); case SYS_WINRESIZE: return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3); case SYS_PROCLIST: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2); case SYS_KILL: { // Free heap allocations for the target process before killing it @@ -217,8 +271,10 @@ namespace Montauk { return (int64_t)Sys_Kill((int)frame->arg1); } case SYS_DEVLIST: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2); case SYS_DISKINFO: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2); case SYS_WINSETSCALE: return (int64_t)Sys_WinSetScale((int)frame->arg1); @@ -227,41 +283,53 @@ namespace Montauk { case SYS_WINSETCURSOR: return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2); case SYS_MEMSTATS: + if (!ValidUserPtr(frame->arg1)) return -1; Sys_MemStats((MemStats*)frame->arg1); return 0; case SYS_PARTLIST: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2); case SYS_DISKREAD: + if (!ValidUserPtr(frame->arg4)) return -1; return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2, (uint32_t)frame->arg3, (void*)frame->arg4); case SYS_DISKWRITE: + if (!ValidUserPtr(frame->arg4)) return -1; return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2, (uint32_t)frame->arg3, (const void*)frame->arg4); case SYS_GPTINIT: return (int64_t)Sys_GptInit((int)frame->arg1); case SYS_GPTADD: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1); case SYS_FSMOUNT: return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2); case SYS_FSFORMAT: + if (!ValidUserPtr(frame->arg1)) return -1; return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1); case SYS_AUDIOOPEN: return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3); case SYS_AUDIOCLOSE: return Sys_AudioClose((int)frame->arg1); case SYS_AUDIOWRITE: + if (!ValidUserPtr(frame->arg2)) return -1; return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3); case SYS_AUDIOCTL: return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3); case SYS_BTSCAN: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3); case SYS_BTCONNECT: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_BtConnect((const uint8_t*)frame->arg1); case SYS_BTDISCONNECT: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_BtDisconnect((const uint8_t*)frame->arg1); case SYS_BTLIST: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2); case SYS_BTINFO: + if (!ValidUserPtr(frame->arg1)) return -1; return Sys_BtInfo((BtAdapterInfo*)frame->arg1); default: return -1; diff --git a/kernel/src/Api/WinServer.cpp b/kernel/src/Api/WinServer.cpp index 6ebcd8c..c2c1732 100644 --- a/kernel/src/Api/WinServer.cpp +++ b/kernel/src/Api/WinServer.cpp @@ -29,8 +29,8 @@ namespace WinServer { } if (slotIdx < 0) return -1; - // Validate dimensions - if (w <= 0 || h <= 0) return -1; + // Validate dimensions (cap at 16384 to prevent integer overflow in w*h*4) + if (w <= 0 || h <= 0 || w > 16384 || h > 16384) return -1; uint64_t bufSize = (uint64_t)w * h * 4; int numPages = (int)((bufSize + 0xFFF) / 0x1000); if (numPages > MaxPixelPages) return -1; @@ -207,7 +207,7 @@ namespace WinServer { if (windowId < 0 || windowId >= MaxWindows) return -1; WindowSlot& slot = g_slots[windowId]; if (!slot.used || slot.ownerPid != callerPid) return -1; - if (newW <= 0 || newH <= 0) return -1; + if (newW <= 0 || newH <= 0 || newW > 16384 || newH > 16384) return -1; if (newW == slot.width && newH == slot.height) { outVa = slot.ownerVa; return 0; diff --git a/kernel/src/Fs/Ramdisk.cpp b/kernel/src/Fs/Ramdisk.cpp index 9ded4f2..4f23d51 100644 --- a/kernel/src/Fs/Ramdisk.cpp +++ b/kernel/src/Fs/Ramdisk.cpp @@ -338,6 +338,73 @@ namespace Fs::Ramdisk { return fileCount++; } + int Delete(const char* path) { + if (path == nullptr) return -1; + if (path[0] == '/') path++; + + for (int i = 0; i < fileCount; i++) { + if (StrEqual(fileTable[i].name, path)) { + // Free heap-allocated data + if (fileTable[i].heapAllocated && fileTable[i].data) { + Memory::g_heap->Free(fileTable[i].data); + } + + // Shift remaining entries down + for (int j = i; j < fileCount - 1; j++) { + fileTable[j] = fileTable[j + 1]; + } + fileCount--; + return 0; + } + } + return -1; // not found + } + + int Mkdir(const char* path) { + if (path == nullptr) return -1; + if (fileCount >= MaxFiles) return -1; + if (path[0] == '/') path++; + + // Check if directory already exists + for (int i = 0; i < fileCount; i++) { + if (StrEqual(fileTable[i].name, path) && fileTable[i].isDirectory) { + return 0; // already exists + } + // Also check with trailing slash + int pathLen = StrLen(path); + int entryLen = StrLen(fileTable[i].name); + if (entryLen == pathLen + 1 && fileTable[i].name[entryLen - 1] == '/' && + fileTable[i].isDirectory) { + bool match = true; + for (int j = 0; j < pathLen; j++) { + if (path[j] != fileTable[i].name[j]) { match = false; break; } + } + if (match) return 0; + } + } + + // Create directory entry (stored with trailing slash for tar convention) + FileEntry& entry = fileTable[fileCount]; + + int nameLen = 0; + while (nameLen < MaxNameLen - 2 && path[nameLen] != '\0') { + entry.name[nameLen] = path[nameLen]; + nameLen++; + } + // Add trailing slash + entry.name[nameLen++] = '/'; + entry.name[nameLen] = '\0'; + + entry.data = nullptr; + entry.size = 0; + entry.capacity = 0; + entry.isDirectory = true; + entry.heapAllocated = false; + + fileCount++; + return 0; + } + int GetFileCount() { return fileCount; } diff --git a/kernel/src/Fs/Ramdisk.hpp b/kernel/src/Fs/Ramdisk.hpp index e1f2ca8..45195e9 100644 --- a/kernel/src/Fs/Ramdisk.hpp +++ b/kernel/src/Fs/Ramdisk.hpp @@ -32,6 +32,8 @@ namespace Fs::Ramdisk { void Close(int handle); int ReadDir(const char* path, const char** outNames, int maxEntries); + int Delete(const char* path); + int Mkdir(const char* path); int GetFileCount(); } diff --git a/kernel/src/Main.cpp b/kernel/src/Main.cpp index 5489b20..6d07e17 100644 --- a/kernel/src/Main.cpp +++ b/kernel/src/Main.cpp @@ -199,8 +199,8 @@ extern "C" void kmain() { Fs::Ramdisk::ReadDir, Fs::Ramdisk::Write, Fs::Ramdisk::Create, - nullptr, - nullptr + Fs::Ramdisk::Delete, + Fs::Ramdisk::Mkdir }; Fs::Vfs::RegisterDrive(0, &ramdiskDriver); } diff --git a/kernel/src/Memory/PageFrameAllocator.cpp b/kernel/src/Memory/PageFrameAllocator.cpp index 0782cf8..8e2d6eb 100644 --- a/kernel/src/Memory/PageFrameAllocator.cpp +++ b/kernel/src/Memory/PageFrameAllocator.cpp @@ -63,6 +63,7 @@ namespace Memory { void* PageFrameAllocator::AllocateZeroed() { auto page = Allocate(); + if (page == nullptr) return nullptr; memset(page, 0, 0x1000); return page; diff --git a/kernel/src/Net/Dns.cpp b/kernel/src/Net/Dns.cpp index 3eebc62..34a15a2 100644 --- a/kernel/src/Net/Dns.cpp +++ b/kernel/src/Net/Dns.cpp @@ -171,7 +171,9 @@ namespace Net::Dns { // Compression pointer if (offset + 1 >= packetLen) return -1; if (!jumped) returnOffset = offset + 2; - offset = ((len & 0x3F) << 8) | packet[offset + 1]; + int target = ((len & 0x3F) << 8) | packet[offset + 1]; + if (target >= packetLen) return -1; // Pointer beyond packet bounds + offset = target; jumped = true; maxJumps--; continue; diff --git a/kernel/src/Net/Ipv4.cpp b/kernel/src/Net/Ipv4.cpp index d010a2c..929dd68 100644 --- a/kernel/src/Net/Ipv4.cpp +++ b/kernel/src/Net/Ipv4.cpp @@ -121,7 +121,7 @@ namespace Net::Ipv4 { } uint16_t totalLen = Ntohs(hdr->TotalLength); - if (totalLen > length) { + if (totalLen < ihl || totalLen > length) { return; } diff --git a/kernel/src/Sched/Scheduler.cpp b/kernel/src/Sched/Scheduler.cpp index d1f503d..d0f9f59 100644 --- a/kernel/src/Sched/Scheduler.cpp +++ b/kernel/src/Sched/Scheduler.cpp @@ -120,6 +120,9 @@ namespace Sched { // Load ELF into the process's address space uint64_t entry = ElfLoad(vfsPath, pml4Phys); if (entry == 0) { + // Free the PML4 and any pages allocated during ELF load + Memory::VMM::Paging::FreeUserHalf(pml4Phys); + Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys)); return -1; } @@ -127,18 +130,29 @@ namespace Sched { void* firstPage = Memory::g_pfa->AllocateZeroed(); if (firstPage == nullptr) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for kernel stack"; + Memory::VMM::Paging::FreeUserHalf(pml4Phys); + Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys)); return -1; } void* stackMem = Memory::g_pfa->ReallocConsecutive(firstPage, StackPages); if (stackMem == nullptr) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to allocate contiguous kernel stack"; Memory::g_pfa->Free(firstPage); + Memory::VMM::Paging::FreeUserHalf(pml4Phys); + Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys)); return -1; } uint8_t* kernelStackBase = (uint8_t*)stackMem; uint64_t kernelStackTop = (uint64_t)kernelStackBase + StackSize; + // Helper to clean up all resources allocated so far on failure + auto cleanupOnFail = [&]() { + Memory::VMM::Paging::FreeUserHalf(pml4Phys); + Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys)); + Memory::g_pfa->Free(stackMem, StackPages); + }; + // Allocate user stack pages and map them in the process PML4 uint64_t userStackBase = UserStackTop - UserStackSize; uint64_t topStackPagePhys = 0; @@ -146,11 +160,14 @@ namespace Sched { void* page = Memory::g_pfa->AllocateZeroed(); if (page == nullptr) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for user stack"; + cleanupOnFail(); return -1; } uint64_t physAddr = Memory::SubHHDM((uint64_t)page); if (!Memory::VMM::Paging::MapUserIn(pml4Phys, physAddr, userStackBase + i * 0x1000)) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map user stack page"; + Memory::g_pfa->Free(page); + cleanupOnFail(); return -1; } if (i == UserStackPages - 1) topStackPagePhys = physAddr; @@ -162,11 +179,14 @@ namespace Sched { void* stubPage = Memory::g_pfa->AllocateZeroed(); if (stubPage == nullptr) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for exit stub"; + cleanupOnFail(); return -1; } uint64_t stubPhys = Memory::SubHHDM((uint64_t)stubPage); if (!Memory::VMM::Paging::MapUserIn(pml4Phys, stubPhys, ExitStubAddr)) { Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map exit stub"; + Memory::g_pfa->Free(stubPage); + cleanupOnFail(); return -1; } @@ -291,19 +311,26 @@ namespace Sched { oldRspPtr = &idleSavedRsp; } + int oldPid = currentPid; currentPid = next; processTable[next].state = ProcessState::Running; processTable[next].sliceRemaining = TimeSliceMs; uint64_t newCR3 = processTable[next].pml4Phys; + // Disable interrupts while updating global kernel RSP and TSS, + // preventing an interrupt from using stale values mid-update. + asm volatile("cli"); + // Update kernel RSP for SYSCALL entry g_kernelRsp = processTable[next].kernelStackTop; // Update TSS RSP0 for hardware interrupts from ring 3 Hal::g_tss.rsp0 = processTable[next].kernelStackTop; - uint8_t* oldFpu = (currentPid >= 0) ? processTable[currentPid].fpuState : nullptr; + asm volatile("sti"); + + uint8_t* oldFpu = (oldPid >= 0) ? processTable[oldPid].fpuState : nullptr; uint8_t* newFpu = processTable[next].fpuState; SchedContextSwitch(oldRspPtr, processTable[next].savedRsp, newCR3, oldFpu, newFpu); } diff --git a/programs/GNUmakefile b/programs/GNUmakefile index a073261..31ff8ae 100644 --- a/programs/GNUmakefile +++ b/programs/GNUmakefile @@ -59,7 +59,7 @@ BINDIR := bin PROGRAMS := $(notdir $(wildcard src/*)) # Programs with custom Makefiles (built separately). -CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop +CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop login shell SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS)) # Build targets: system programs go to bin/os/, apps go to bin/apps//. @@ -78,12 +78,12 @@ WWWDST := $(patsubst $(WWWDIR)/%,$(BINDIR)/www/%,$(WWWSRC)) # CA certificate bundle. CA_CERTS := $(BINDIR)/etc/ca-certificates.crt -# Home directory placeholder. -HOMEKEEP := $(BINDIR)/home/.keep +# Common shared assets (wallpapers, etc.) +COMMONKEEP := $(BINDIR)/common/.keep -.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop icons fonts bearssl libc tls libjpeg install-apps +.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth login desktop shell icons fonts bearssl libc tls libjpeg install-apps -all: bearssl libc libjpeg tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom desktop icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(HOMEKEEP) +all: bearssl libc libjpeg tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom login desktop shell icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP) # Build BearSSL static library (cross-compiled for freestanding x86_64). BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc) @@ -164,8 +164,16 @@ music: libc bluetooth: libc $(MAKE) -C src/bluetooth -# Build desktop via its own Makefile (depends on libc and libjpeg for wallpaper). -desktop: libc libjpeg +# Build login screen via its own Makefile (depends on bearssl and libc). +login: bearssl libc + $(MAKE) -C src/login + +# Build shell via its own Makefile (multi-file build). +shell: + $(MAKE) -C src/shell + +# Build desktop via its own Makefile (depends on libc, libjpeg, and bearssl for user.h). +desktop: libc libjpeg bearssl $(MAKE) -C src/desktop # Copy SVG icons for the desktop into bin/icons/. @@ -199,9 +207,9 @@ $(CA_CERTS): data/ca-certificates.crt mkdir -p $(BINDIR)/etc cp $< $@ -# Create empty home directory with a keep file. -$(HOMEKEEP): - mkdir -p $(BINDIR)/home +# Ensure common assets directory exists. +$(COMMONKEEP): + mkdir -p $(BINDIR)/common touch $@ # Build each system program from its source files. @@ -218,6 +226,8 @@ clean: $(MAKE) -C lib/tls clean $(MAKE) -C src/fetch clean $(MAKE) -C src/doom clean + $(MAKE) -C src/login clean + $(MAKE) -C src/shell clean $(MAKE) -C src/desktop clean $(MAKE) -C src/wikipedia clean $(MAKE) -C src/weather clean diff --git a/programs/include/gui/desktop.hpp b/programs/include/gui/desktop.hpp index 4af2abf..098b678 100644 --- a/programs/include/gui/desktop.hpp +++ b/programs/include/gui/desktop.hpp @@ -60,6 +60,12 @@ struct DesktopState { int window_count; int focused_window; + // Current user context + char current_user[32]; + char home_dir[128]; // "0:/users/" + char user_config_dir[128]; // "0:/users//config" + bool is_admin; + Montauk::MouseState mouse; uint8_t prev_buttons; @@ -93,9 +99,11 @@ struct DesktopState { SvgIcon icon_settings; SvgIcon icon_reboot; SvgIcon icon_shutdown; + SvgIcon icon_logout; SvgIcon icon_procmgr; SvgIcon icon_mandelbrot; + SvgIcon icon_volume; // External apps discovered from 0:/apps/ manifests ExternalApp external_apps[MAX_EXTERNAL_APPS]; @@ -109,6 +117,14 @@ struct DesktopState { uint64_t net_cfg_last_poll; Rect net_icon_rect; + bool vol_popup_open; + Rect vol_icon_rect; + int vol_level; // 0-100 + bool vol_muted; + int vol_pre_mute; // volume before mute + bool vol_dragging; // slider drag in progress + uint64_t vol_last_poll; + int screen_w, screen_h; // IDs of external windows we've sent a close event to but that haven't @@ -119,6 +135,15 @@ struct DesktopState { int closing_ext_count; DesktopSettings settings; + + // Lock screen state + bool screen_locked; + char lock_password[64]; + int lock_password_len; + char lock_error[128]; + bool lock_show_error; + char lock_display_name[64]; + SvgIcon icon_lock; }; // Forward declarations - implemented in main.cpp diff --git a/programs/include/http/http.hpp b/programs/include/http/http.hpp new file mode 100644 index 0000000..8a10eb5 --- /dev/null +++ b/programs/include/http/http.hpp @@ -0,0 +1,316 @@ +/* + * http.hpp + * Simple HTTP request builder and response parser for MontaukOS + * Wraps tls::https_fetch() and raw sockets for ergonomic HTTP usage. + */ + +#pragma once + +#include +#include +#include +#include + +namespace http { + +// ---------------------------------------------------------------------------- +// Response +// ---------------------------------------------------------------------------- + +struct Response { + int status; // HTTP status code (200, 404, etc.) or -1 on error + const char* headers; // Pointer into raw buffer (header block) + int headers_len; + const char* body; // Pointer into raw buffer (body) + int body_len; + char* raw; // Owned buffer — caller must free with montauk::mfree() + int raw_len; +}; + +// Parse raw HTTP response in-place. Sets pointers into buf (does not copy). +// Returns status code, or -1 if unparseable. +inline int parse_response(char* buf, int len, Response* out) { + out->raw = buf; + out->raw_len = len; + out->status = -1; + out->headers = nullptr; + out->headers_len = 0; + out->body = nullptr; + out->body_len = 0; + + if (len < 12) return -1; // "HTTP/1.x NNN" + + // Parse status code from "HTTP/1.x NNN" + const char* p = buf; + while (*p && *p != ' ') p++; + if (*p != ' ') return -1; + p++; + int code = 0; + for (int i = 0; i < 3 && *p >= '0' && *p <= '9'; i++, p++) + code = code * 10 + (*p - '0'); + out->status = code; + + // Headers start after the status line + const char* hdr_start = buf; + while (hdr_start < buf + len - 1) { + if (*hdr_start == '\r' && *(hdr_start + 1) == '\n') { hdr_start += 2; break; } + if (*hdr_start == '\n') { hdr_start++; break; } + hdr_start++; + } + out->headers = hdr_start; + + // Find \r\n\r\n boundary between headers and body + for (const char* s = hdr_start; s < buf + len - 3; s++) { + if (s[0] == '\r' && s[1] == '\n' && s[2] == '\r' && s[3] == '\n') { + out->headers_len = (int)(s - hdr_start); + out->body = s + 4; + out->body_len = len - (int)(out->body - buf); + return code; + } + } + // No body separator found — entire remainder is headers + out->headers_len = len - (int)(hdr_start - buf); + return code; +} + +// Find a header value by name (case-insensitive match on the name). +// Writes value into out_val (up to max_len), returns true if found. +inline bool get_header(const Response* resp, const char* name, char* out_val, int max_len) { + if (!resp->headers || resp->headers_len == 0) return false; + int name_len = montauk::slen(name); + const char* p = resp->headers; + const char* end = resp->headers + resp->headers_len; + + while (p < end) { + // Case-insensitive prefix match + bool match = true; + if (p + name_len >= end) { match = false; } + else { + for (int i = 0; i < name_len; i++) { + char a = p[i], b = name[i]; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) { match = false; break; } + } + if (match && p[name_len] != ':') match = false; + } + + if (match) { + const char* v = p + name_len + 1; + while (v < end && *v == ' ') v++; // skip OWS + int i = 0; + while (v < end && *v != '\r' && *v != '\n' && i < max_len - 1) + out_val[i++] = *v++; + out_val[i] = 0; + return true; + } + + // Skip to next line + while (p < end && *p != '\n') p++; + if (p < end) p++; + } + return false; +} + +// Free a response's raw buffer. +inline void free_response(Response* resp) { + if (resp->raw) { montauk::mfree(resp->raw); resp->raw = nullptr; } +} + +// ---------------------------------------------------------------------------- +// Request builder (internal) +// ---------------------------------------------------------------------------- + +inline int build_request(char* buf, int buf_size, + const char* method, const char* host, + const char* path, const char* content_type, + const char* body_data, int body_len, + const char* extra_headers) { + char* p = buf; + char* end = buf + buf_size - 1; + + auto append = [&](const char* s) { + while (*s && p < end) *p++ = *s++; + }; + auto append_int = [&](int n) { + char tmp[16]; int ti = 0; + if (n == 0) { if (p < end) *p++ = '0'; return; } + while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; } + for (int j = ti - 1; j >= 0 && p < end; j--) *p++ = tmp[j]; + }; + + // Request line + append(method); append(" "); append(path); append(" HTTP/1.1\r\n"); + + // Host + append("Host: "); append(host); append("\r\n"); + + // Content headers (for POST/PUT/PATCH) + if (body_data && body_len > 0) { + if (content_type) { + append("Content-Type: "); append(content_type); append("\r\n"); + } + append("Content-Length: "); append_int(body_len); append("\r\n"); + } + + // Extra headers (caller-supplied, must include \r\n terminators) + if (extra_headers) append(extra_headers); + + append("Connection: close\r\n"); + append("\r\n"); + + int header_len = (int)(p - buf); + + // Append body + if (body_data && body_len > 0 && header_len + body_len < buf_size) { + montauk::memcpy(p, body_data, body_len); + p += body_len; + } + + return (int)(p - buf); +} + +// ---------------------------------------------------------------------------- +// Public API +// ---------------------------------------------------------------------------- + +// GET request over HTTPS. Returns parsed response. Caller must free_response(). +inline Response get(const char* host, const char* path, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + char req[1024]; + int reqLen = build_request(req, sizeof(req), "GET", host, path, + nullptr, nullptr, 0, extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) return resp; + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// POST request over HTTPS. Returns parsed response. Caller must free_response(). +inline Response post(const char* host, const char* path, + const char* content_type, + const char* body_data, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + int req_size = 1024 + body_len; + char* req = (char*)montauk::malloc(req_size); + if (!req) return resp; + + int reqLen = build_request(req, req_size, "POST", host, path, + content_type, body_data, body_len, + extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::mfree(req); return resp; } + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + montauk::mfree(req); + + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// Generic request over HTTPS (PUT, PATCH, DELETE, etc.). +inline Response request(const char* method, + const char* host, const char* path, + const char* content_type, + const char* body_data, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + int req_size = 1024 + (body_len > 0 ? body_len : 0); + char* req = (char*)montauk::malloc(req_size); + if (!req) return resp; + + int reqLen = build_request(req, req_size, method, host, path, + content_type, body_data, body_len, + extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::mfree(req); return resp; } + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + montauk::mfree(req); + + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// Plain HTTP (no TLS) GET over port 80. +inline Response get_plain(const char* host, const char* path, + int resp_buf_size = 32768, + const char* extra_headers = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + char req[1024]; + int reqLen = build_request(req, sizeof(req), "GET", host, path, + nullptr, nullptr, 0, extra_headers); + + int sock = montauk::socket(Montauk::SOCK_TCP); + if (sock < 0) return resp; + if (montauk::connect(sock, ip, 80) < 0) { montauk::closesocket(sock); return resp; } + + montauk::send(sock, req, reqLen); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::closesocket(sock); return resp; } + + int total = 0; + while (total < resp_buf_size - 1) { + int n = montauk::recv(sock, buf + total, resp_buf_size - 1 - total); + if (n <= 0) break; + total += n; + } + montauk::closesocket(sock); + + if (total <= 0) { montauk::mfree(buf); return resp; } + buf[total] = 0; + + parse_response(buf, total, &resp); + return resp; +} + +} // namespace http diff --git a/programs/include/montauk/config.h b/programs/include/montauk/config.h index 180924b..eda5df4 100644 --- a/programs/include/montauk/config.h +++ b/programs/include/montauk/config.h @@ -247,14 +247,98 @@ namespace config { char* text = serialize(doc); int textLen = montauk::slen(text); - // Try to open existing file, create if not found + // Delete and recreate to ensure file is exactly the right size + // (no ftruncate syscall available, so this avoids stale trailing data) + montauk::fdelete(path); + int handle = montauk::fcreate(path); + if (handle < 0) { + montauk::mfree(text); + return -1; + } + + int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen); + montauk::close(handle); + montauk::mfree(text); + return ret < 0 ? ret : 0; + } + + // ---- Per-user config ---- + + // Build path: "0:/users//config/.toml" + inline void build_user_path(char* out, int outSz, const char* username, const char* name) { + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < outSz - 2) out[p++] = *prefix++; + while (*username && p < outSz - 2) out[p++] = *username++; + const char* mid = "/config/"; + while (*mid && p < outSz - 2) out[p++] = *mid++; + while (*name && p < outSz - 6) out[p++] = *name++; + const char* ext = ".toml"; + while (*ext && p < outSz - 1) out[p++] = *ext++; + out[p] = '\0'; + } + + // Ensure per-user config directory exists + inline void ensure_user_dir(const char* username) { + char dir[128]; + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < 126) dir[p++] = *prefix++; + while (*username && p < 126) dir[p++] = *username++; + dir[p] = '\0'; + montauk::fmkdir(dir); + + const char* suffix = "/config"; + while (*suffix && p < 126) dir[p++] = *suffix++; + dir[p] = '\0'; + montauk::fmkdir(dir); + } + + // Load a per-user config file + inline toml::Doc load_user(const char* username, const char* name) { + char path[192]; + build_user_path(path, sizeof(path), username, name); + int handle = montauk::open(path); if (handle < 0) { - handle = montauk::fcreate(path); - if (handle < 0) { - montauk::mfree(text); - return -1; - } + toml::Doc doc; + doc.init(); + return doc; + } + + uint64_t size = montauk::getsize(handle); + if (size == 0) { + montauk::close(handle); + toml::Doc doc; + doc.init(); + return doc; + } + + char* text = (char*)montauk::malloc(size + 1); + montauk::read(handle, (uint8_t*)text, 0, size); + montauk::close(handle); + text[size] = '\0'; + + toml::Doc doc = toml::parse(text); + montauk::mfree(text); + return doc; + } + + // Save a per-user config file + inline int save_user(const char* username, const char* name, toml::Doc* doc) { + ensure_user_dir(username); + + char path[192]; + build_user_path(path, sizeof(path), username, name); + + char* text = serialize(doc); + int textLen = montauk::slen(text); + + montauk::fdelete(path); + int handle = montauk::fcreate(path); + if (handle < 0) { + montauk::mfree(text); + return -1; } int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen); @@ -272,12 +356,28 @@ namespace config { // ---- In-place modification helpers ---- + // Free any dynamically allocated data owned by a value (without freeing key) + namespace detail { + inline void free_value_data(toml::Value* v) { + if (v->type == toml::Type::String && v->str) + montauk::mfree(v->str); + else if (v->type == toml::Type::Array || v->type == toml::Type::Table) { + for (int i = 0; i < v->array.count; i++) { + if (v->array.items[i]) v->array.items[i]->destroy(); + } + if (v->array.items) montauk::mfree(v->array.items); + v->array.items = nullptr; + v->array.count = 0; + v->array.cap = 0; + } + } + } + // Set or overwrite a string value in the doc. inline void set_string(toml::Doc* doc, const char* key, const char* val) { auto* existing = doc->get(key); if (existing) { - if (existing->type == toml::Type::String && existing->str) - montauk::mfree(existing->str); + detail::free_value_data(existing); existing->type = toml::Type::String; existing->str = toml::Value::dup(val); } else { @@ -289,8 +389,7 @@ namespace config { inline void set_int(toml::Doc* doc, const char* key, int64_t val) { auto* existing = doc->get(key); if (existing) { - if (existing->type == toml::Type::String && existing->str) - montauk::mfree(existing->str); + detail::free_value_data(existing); existing->type = toml::Type::Int; existing->ival = val; } else { @@ -302,8 +401,7 @@ namespace config { inline void set_bool(toml::Doc* doc, const char* key, bool val) { auto* existing = doc->get(key); if (existing) { - if (existing->type == toml::Type::String && existing->str) - montauk::mfree(existing->str); + detail::free_value_data(existing); existing->type = toml::Type::Bool; existing->bval = val; } else { diff --git a/programs/include/montauk/heap.h b/programs/include/montauk/heap.h index 1fa0e72..283eeac 100644 --- a/programs/include/montauk/heap.h +++ b/programs/include/montauk/heap.h @@ -151,6 +151,10 @@ namespace heap_detail { g_initialized = true; } + // Guard against overflow: size + Header must not wrap + if (size > UINT64_MAX - sizeof(Header) - 15) + return nullptr; + uint64_t needed = size + sizeof(Header); needed = (needed + 15) & ~15ULL; diff --git a/programs/include/montauk/string.h b/programs/include/montauk/string.h index c85d982..821a506 100644 --- a/programs/include/montauk/string.h +++ b/programs/include/montauk/string.h @@ -99,6 +99,7 @@ namespace montauk { } inline void strncpy(char* dst, const char* src, int max) { + if (max <= 0) return; int i = 0; while (src[i] && i < max - 1) { dst[i] = src[i]; i++; } dst[i] = '\0'; diff --git a/programs/include/montauk/user.h b/programs/include/montauk/user.h new file mode 100644 index 0000000..0324ecd --- /dev/null +++ b/programs/include/montauk/user.h @@ -0,0 +1,338 @@ +/* + * user.h + * User database, password hashing, and authentication for MontaukOS + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include +#include +#include +#include +#include + +namespace montauk { +namespace user { + + static constexpr int MAX_USERS = 16; + + struct UserInfo { + char username[32]; + char display_name[64]; + char password_hash[65]; // 64 hex chars + null + char salt[33]; // 32 hex chars + null + char role[16]; + }; + + // ---- String helpers ---- + + inline void str_cat(char* dst, const char* src, int max) { + int len = montauk::slen(dst); + int i = 0; + while (src[i] && len < max - 1) { + dst[len++] = src[i++]; + } + dst[len] = '\0'; + } + + inline void build_user_key(char* out, int sz, const char* username, const char* field) { + int p = 0; + const char* prefix = "users."; + while (*prefix && p < sz - 1) out[p++] = *prefix++; + while (*username && p < sz - 1) out[p++] = *username++; + if (p < sz - 1) out[p++] = '.'; + while (*field && p < sz - 1) out[p++] = *field++; + out[p] = '\0'; + } + + // ---- Path helpers ---- + + inline void home_dir(const char* username, char* out, int sz) { + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < sz - 1) out[p++] = *prefix++; + while (*username && p < sz - 1) out[p++] = *username++; + out[p] = '\0'; + } + + inline void config_dir(const char* username, char* out, int sz) { + home_dir(username, out, sz); + str_cat(out, "/config", sz); + } + + // ---- Hex conversion helpers ---- + + inline void bytes_to_hex(const uint8_t* bytes, int len, char* out) { + const char* digits = "0123456789abcdef"; + for (int i = 0; i < len; i++) { + out[i * 2] = digits[(bytes[i] >> 4) & 0x0F]; + out[i * 2 + 1] = digits[bytes[i] & 0x0F]; + } + out[len * 2] = '\0'; + } + + inline int hex_char_val(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return 10 + c - 'a'; + if (c >= 'A' && c <= 'F') return 10 + c - 'A'; + return -1; + } + + inline int hex_to_bytes(const char* hex, uint8_t* out, int maxBytes) { + int i = 0; + while (hex[i * 2] && hex[i * 2 + 1] && i < maxBytes) { + int hi = hex_char_val(hex[i * 2]); + int lo = hex_char_val(hex[i * 2 + 1]); + if (hi < 0 || lo < 0) return i; + out[i] = (uint8_t)((hi << 4) | lo); + i++; + } + return i; + } + + // ---- Password hashing (SHA-256) ---- + + inline void hash_password(const char* password, const char* salt_hex, char* out_hex64) { + uint8_t salt_bytes[16]; + int salt_len = hex_to_bytes(salt_hex, salt_bytes, 16); + int pass_len = montauk::slen(password); + + br_sha256_context ctx; + br_sha256_init(&ctx); + br_sha256_update(&ctx, salt_bytes, salt_len); + br_sha256_update(&ctx, password, pass_len); + + uint8_t hash[32]; + br_sha256_out(&ctx, hash); + bytes_to_hex(hash, 32, out_hex64); + } + + inline bool verify_password(const char* password, const char* salt_hex, const char* stored_hex64) { + char computed[65]; + hash_password(password, salt_hex, computed); + + int diff = 0; + for (int i = 0; i < 64; i++) { + diff |= computed[i] ^ stored_hex64[i]; + } + return diff == 0; + } + + // ---- User database I/O ---- + + inline int load_users(UserInfo* buf, int max) { + auto doc = config::load("users"); + int count = 0; + + for (int i = 0; i < doc.entries.count && count < max; i++) { + auto* v = doc.entries.items[i]; + if (!v->key) continue; + + if (!montauk::starts_with(v->key, "users.")) continue; + const char* after = v->key + 6; + + int dot = -1; + for (int j = 0; after[j]; j++) { + if (after[j] == '.') { dot = j; break; } + } + if (dot <= 0) continue; + + if (!montauk::streq(after + dot + 1, "display_name")) continue; + + UserInfo* u = &buf[count]; + montauk::memset(u, 0, sizeof(UserInfo)); + int ulen = dot < 31 ? dot : 31; + montauk::memcpy(u->username, after, ulen); + u->username[ulen] = '\0'; + + if (v->type == montauk::toml::Type::String && v->str) + montauk::strncpy(u->display_name, v->str, sizeof(u->display_name)); + + char prefix[64]; + int plen = 0; + const char* pfx = "users."; + while (*pfx) prefix[plen++] = *pfx++; + for (int j = 0; j < ulen; j++) prefix[plen++] = u->username[j]; + prefix[plen] = '\0'; + + char key[96]; + + montauk::strcpy(key, prefix); + str_cat(key, ".password_hash", 96); + const char* ph = doc.get_string(key, ""); + montauk::strncpy(u->password_hash, ph, sizeof(u->password_hash)); + + montauk::strcpy(key, prefix); + str_cat(key, ".salt", 96); + const char* s = doc.get_string(key, ""); + montauk::strncpy(u->salt, s, sizeof(u->salt)); + + montauk::strcpy(key, prefix); + str_cat(key, ".role", 96); + const char* r = doc.get_string(key, "user"); + montauk::strncpy(u->role, r, sizeof(u->role)); + + count++; + } + + doc.destroy(); + return count; + } + + inline int save_users(const UserInfo* buf, int count) { + montauk::toml::Doc doc; + doc.init(); + + for (int i = 0; i < count; i++) { + const UserInfo* u = &buf[i]; + char key[96]; + + build_user_key(key, 96, u->username, "display_name"); + config::set_string(&doc, key, u->display_name); + + build_user_key(key, 96, u->username, "password_hash"); + config::set_string(&doc, key, u->password_hash); + + build_user_key(key, 96, u->username, "salt"); + config::set_string(&doc, key, u->salt); + + build_user_key(key, 96, u->username, "role"); + config::set_string(&doc, key, u->role); + } + + int ret = config::save("users", &doc); + doc.destroy(); + return ret; + } + + // ---- Authentication ---- + + inline bool authenticate(const char* username, const char* password) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { + return verify_password(password, users[i].salt, users[i].password_hash); + } + } + return false; + } + + // ---- User management ---- + + inline bool create_user(const char* username, const char* display_name, + const char* password, const char* role) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) return false; + } + if (count >= MAX_USERS) return false; + + UserInfo* u = &users[count]; + montauk::memset(u, 0, sizeof(UserInfo)); + montauk::strncpy(u->username, username, 31); + montauk::strncpy(u->display_name, display_name, 63); + montauk::strncpy(u->role, role, 15); + + uint8_t salt_bytes[16]; + montauk::getrandom(salt_bytes, 16); + bytes_to_hex(salt_bytes, 16, u->salt); + + hash_password(password, u->salt, u->password_hash); + + count++; + save_users(users, count); + + // Create home directory structure + char dir[128]; + home_dir(username, dir, sizeof(dir)); + montauk::fmkdir(dir); + + char subdir[128]; + montauk::strcpy(subdir, dir); + str_cat(subdir, "/config", 128); + montauk::fmkdir(subdir); + + return true; + } + + inline bool delete_user(const char* username) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + int idx = -1; + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { idx = i; break; } + } + if (idx < 0) return false; + + for (int i = idx; i < count - 1; i++) { + users[i] = users[i + 1]; + } + count--; + + save_users(users, count); + return true; + } + + inline bool change_password(const char* username, const char* new_password) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { + uint8_t salt_bytes[16]; + montauk::getrandom(salt_bytes, 16); + bytes_to_hex(salt_bytes, 16, users[i].salt); + + hash_password(new_password, users[i].salt, users[i].password_hash); + + save_users(users, count); + return true; + } + } + return false; + } + + // ---- Session (current logged-in user) ---- + + // Write the current session after successful login. + // Stores username in 0:/config/session.toml so any app can query it. + inline void set_session(const char* username) { + montauk::toml::Doc doc; + doc.init(); + config::set_string(&doc, "session.username", username); + config::save("session", &doc); + doc.destroy(); + } + + // Clear the session (on logout). + inline void clear_session() { + montauk::fdelete("0:/config/session.toml"); + } + + // Read the current username into buf. Returns true if a session exists. + inline bool get_session_username(char* buf, int bufSz) { + auto doc = config::load("session"); + const char* name = doc.get_string("session.username", ""); + bool found = (name[0] != '\0'); + if (found) { + montauk::strncpy(buf, name, bufSz); + } + doc.destroy(); + return found; + } + + // Get the current user's home directory. Returns true if a session exists. + inline bool get_home_dir(char* buf, int bufSz) { + char username[32]; + if (!get_session_username(username, sizeof(username))) return false; + home_dir(username, buf, bufSz); + return true; + } + +} // namespace user +} // namespace montauk diff --git a/programs/lib/libc/libc.c b/programs/lib/libc/libc.c index 9df0744..ad0833b 100644 --- a/programs/lib/libc/libc.c +++ b/programs/lib/libc/libc.c @@ -395,6 +395,10 @@ void *malloc(size_t size) { g_heapInit = 1; } + /* Guard against overflow: size + Header must not wrap */ + if (size > (uint64_t)-1 - sizeof(struct HeapHeader) - 15) + return NULL; + uint64_t needed = size + sizeof(struct HeapHeader); needed = (needed + 15) & ~15ULL; @@ -455,6 +459,9 @@ void free(void *ptr) { } void *calloc(size_t nmemb, size_t size) { + /* Check for multiplication overflow */ + if (nmemb != 0 && size > (size_t)-1 / nmemb) + return NULL; size_t total = nmemb * size; void *p = malloc(total); if (p) memset(p, 0, total); @@ -540,7 +547,36 @@ long strtol(const char *nptr, char **endptr, int base) { } unsigned long strtoul(const char *nptr, char **endptr, int base) { - return (unsigned long)strtol(nptr, endptr, base); + const char *s = nptr; + unsigned long val = 0; + + while (isspace((unsigned char)*s)) s++; + /* strtoul allows an optional leading + or - (result is negated for -) */ + int neg = 0; + if (*s == '-') { neg = 1; s++; } + else if (*s == '+') { s++; } + + if (base == 0) { + if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; } + else if (*s == '0') { base = 8; s++; } + else base = 10; + } else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) { + s += 2; + } + + while (*s) { + int digit; + if (*s >= '0' && *s <= '9') digit = *s - '0'; + else if (*s >= 'a' && *s <= 'z') digit = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'Z') digit = *s - 'A' + 10; + else break; + if (digit >= base) break; + val = val * (unsigned long)base + (unsigned long)digit; + s++; + } + + if (endptr) *endptr = (char *)s; + return neg ? (unsigned long)(-(long)val) : val; } char *getenv(const char *name) { diff --git a/programs/lib/libc/obj/libc.o b/programs/lib/libc/obj/libc.o index 2747fc517e37f7c367a524ac394bb04bb60fea0a..8955356ab6e757c63d166e9e49ef3dfbadb3e971 100644 GIT binary patch delta 33607 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 diff --git a/programs/man/intro.1 b/programs/man/intro.1 index 4158744..4e1af0c 100644 --- a/programs/man/intro.1 +++ b/programs/man/intro.1 @@ -37,7 +37,8 @@ 0:/games/ Games (doom) 0:/man/ Manual pages 0:/www/ Web server content - 0:/home/ User home directory + 0:/common/ Shared assets (wallpapers, etc.) + 0:/users/ Per-user home directories .SH SHELL The interactive shell is the primary way to interact with diff --git a/programs/src/desktop/Makefile b/programs/src/desktop/Makefile index 044c053..99be105 100644 --- a/programs/src/desktop/Makefile +++ b/programs/src/desktop/Makefile @@ -18,6 +18,7 @@ endif PROG_INC := ../../include JPEG_LIB := ../../lib/libjpeg LIBC_LIB := ../../lib/libc +BEARSSL := ../../lib/bearssl LINK_LD := ../../link.ld BINDIR := ../../bin OBJDIR := obj @@ -48,6 +49,8 @@ CXXFLAGS := \ -mcmodel=small \ -MMD -MP \ -I $(PROG_INC) \ + -isystem $(PROG_INC)/libc \ + -I $(BEARSSL)/inc \ -isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \ -isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include @@ -79,7 +82,7 @@ all: $(TARGET) # ---- Libraries ---- -LIBS := $(JPEG_LIB)/libjpeg.a $(LIBC_LIB)/liblibc.a +LIBS := $(JPEG_LIB)/libjpeg.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a $(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile mkdir -p $(BINDIR)/os diff --git a/programs/src/desktop/apps/app_filemanager.cpp b/programs/src/desktop/apps/app_filemanager.cpp index fed2759..492b7e8 100644 --- a/programs/src/desktop/apps/app_filemanager.cpp +++ b/programs/src/desktop/apps/app_filemanager.cpp @@ -360,7 +360,12 @@ static void filemanager_go_up(FileManagerState* fm) { if (fm->current_path[i] == '/') { last_slash = i; break; } } if (last_slash >= 0) { - fm->current_path[last_slash + 1] = '\0'; + // Keep the slash only if it's the root slash (right after "N:") + if (last_slash > 0 && fm->current_path[last_slash - 1] == ':') { + fm->current_path[last_slash + 1] = '\0'; + } else { + fm->current_path[last_slash] = '\0'; + } } filemanager_push_history(fm); filemanager_read_dir(fm); diff --git a/programs/src/desktop/apps/app_settings.cpp b/programs/src/desktop/apps/app_settings.cpp index 70b9be9..142882d 100644 --- a/programs/src/desktop/apps/app_settings.cpp +++ b/programs/src/desktop/apps/app_settings.cpp @@ -6,6 +6,8 @@ #include "apps_common.hpp" #include "../wallpaper.hpp" +#include +#include // ============================================================================ // Settings state @@ -13,11 +15,20 @@ struct SettingsState { DesktopState* desktop; - int active_tab; // 0=Appearance, 1=Display, 2=About + int active_tab; // 0=Appearance, 1=Display, 2=Users, 3=About Montauk::SysInfo sys_info; uint64_t uptime_ms; WallpaperFileList wp_files; bool wp_scanned; + + // Users tab + montauk::user::UserInfo users[16]; + int user_count; + int selected_user; // index into users[], or -1 + bool users_loaded; + + char status_msg[128]; + uint64_t status_time; }; // ============================================================================ @@ -69,8 +80,8 @@ static const Color accent_palette[SWATCH_COUNT] = { // ============================================================================ static constexpr int TAB_BAR_H = 36; -static constexpr int TAB_COUNT = 3; -static const char* tab_labels[TAB_COUNT] = { "Appearance", "Display", "About" }; +static constexpr int TAB_COUNT = 4; +static const char* tab_labels[TAB_COUNT] = { "Appearance", "Display", "Users", "About" }; // ============================================================================ // Helper: check if two colors match @@ -166,11 +177,11 @@ static void settings_draw_appearance(Canvas& c, SettingsState* st) { if (mode_image) { // Scan for images lazily if (!st->wp_scanned) { - wallpaper_scan_dir("0:/home", &st->wp_files); + wallpaper_scan_dir(st->desktop->home_dir, &st->wp_files); st->wp_scanned = true; } - c.text(x, y, "Images in 0:/home/", dim); + c.text(x, y, "Wallpapers", dim); y += sfh + 6; if (st->wp_files.count == 0) { @@ -180,7 +191,8 @@ static void settings_draw_appearance(Canvas& c, SettingsState* st) { for (int i = 0; i < st->wp_files.count && i < 8; i++) { // Build full path for comparison char fullpath[256]; - montauk::strcpy(fullpath, "0:/home/"); + montauk::strcpy(fullpath, st->desktop->home_dir); + str_append(fullpath, "/", 256); str_append(fullpath, st->wp_files.names[i], 256); bool selected = s.bg_image && @@ -333,6 +345,702 @@ static void settings_draw_about(Canvas& c, SettingsState* st) { c.text(x, y, "Copyright (c) 2026 Daniel Hammer", dim); } +// ============================================================================ +// Config persistence +// ============================================================================ + +static int64_t color_to_int(Color c) { + return ((int64_t)c.r << 16) | ((int64_t)c.g << 8) | c.b; +} + +static Color int_to_color(int64_t v) { + return Color::from_rgb((uint8_t)((v >> 16) & 0xFF), + (uint8_t)((v >> 8) & 0xFF), + (uint8_t)(v & 0xFF)); +} + +static void settings_persist(SettingsState* st) { + DesktopSettings& s = st->desktop->settings; + const char* user = st->desktop->current_user; + + montauk::toml::Doc doc; + doc.init(); + + // Background mode + const char* mode = s.bg_image ? "image" : (s.bg_gradient ? "gradient" : "solid"); + montauk::config::set_string(&doc, "background.mode", mode); + + // Wallpaper path + if (s.bg_image && s.bg_image_path[0]) + montauk::config::set_string(&doc, "wallpaper.path", s.bg_image_path); + + // Background colors + montauk::config::set_int(&doc, "background.solid_color", color_to_int(s.bg_solid)); + montauk::config::set_int(&doc, "background.grad_top", color_to_int(s.bg_grad_top)); + montauk::config::set_int(&doc, "background.grad_bottom", color_to_int(s.bg_grad_bottom)); + + // Appearance + montauk::config::set_int(&doc, "appearance.panel_color", color_to_int(s.panel_color)); + montauk::config::set_int(&doc, "appearance.accent_color", color_to_int(s.accent_color)); + + // Display + montauk::config::set_int(&doc, "display.ui_scale", s.ui_scale); + montauk::config::set_bool(&doc, "display.clock_24h", s.clock_24h); + montauk::config::set_bool(&doc, "display.show_shadows", s.show_shadows); + + montauk::config::save_user(user, "desktop", &doc); + doc.destroy(); +} + +// ============================================================================ +// Users tab +// ============================================================================ + +static void users_reload(SettingsState* st) { + st->user_count = montauk::user::load_users(st->users, 16); + st->users_loaded = true; +} + +static constexpr int USER_BTN_H = 30; +static constexpr int USER_BTN_W = 100; +static constexpr int USER_FIELD_H = 32; + +// Forward declarations for dialog openers +static void open_add_user_dialog(SettingsState* st); +static void open_change_pwd_dialog(SettingsState* st); +static void open_delete_user_dialog(SettingsState* st); + +static int user_row_height() { + return system_font_height() * 2 + 12; // Two lines of text + padding +} + +static void settings_draw_users(Canvas& c, SettingsState* st) { + if (!st->users_loaded) users_reload(st); + + Color accent = st->desktop->settings.accent_color; + Color dim = Color::from_rgb(0x88, 0x88, 0x88); + Color card_bg = Color::from_rgb(0xF8, 0xF8, 0xF8); + int x = 16; + int y = 20; + int sfh = system_font_height(); + int content_w = c.w - 2 * x; + int row_h = user_row_height(); + + if (!st->desktop->is_admin) { + c.text(x, y, "Admin access required to manage users.", dim); + return; + } + + // User list + for (int i = 0; i < st->user_count; i++) { + bool sel = (i == st->selected_user); + bool is_current = montauk::streq(st->users[i].username, st->desktop->current_user); + + if (sel) { + c.fill_rounded_rect(x, y, content_w, row_h, 4, accent); + } else if (i % 2 == 0) { + c.fill_rounded_rect(x, y, content_w, row_h, 4, card_bg); + } + + Color tc = sel ? colors::WHITE : colors::TEXT_COLOR; + Color sc = sel ? Color::from_rgb(0xDD, 0xDD, 0xFF) : dim; + + // Display name (primary line) + int text_y = y + 4; + c.text(x + 12, text_y, st->users[i].display_name, tc); + + // Username (secondary line) + char sub[48]; + if (is_current) { + snprintf(sub, sizeof(sub), "@%s (you)", st->users[i].username); + } else { + snprintf(sub, sizeof(sub), "@%s", st->users[i].username); + } + c.text(x + 12, text_y + sfh + 2, sub, sc); + + // Role badge + const char* role = st->users[i].role; + int rw = text_width(role) + 12; + int badge_x = c.w - x - rw - 8; + int badge_y = y + (row_h - sfh - 4) / 2; + if (sel) { + c.fill_rounded_rect(badge_x, badge_y, rw, sfh + 4, (sfh + 4) / 2, + Color::from_rgb(0xFF, 0xFF, 0xFF)); + c.text(badge_x + 6, badge_y + 2, role, accent); + } else { + bool is_admin_role = montauk::streq(role, "admin"); + Color badge_bg = is_admin_role + ? Color::from_rgb(0xE8, 0xD8, 0xF0) + : Color::from_rgb(0xE0, 0xE8, 0xF0); + Color badge_fg = is_admin_role + ? Color::from_rgb(0x7B, 0x3E, 0xB8) + : Color::from_rgb(0x36, 0x7B, 0xF0); + c.fill_rounded_rect(badge_x, badge_y, rw, sfh + 4, (sfh + 4) / 2, badge_bg); + c.text(badge_x + 6, badge_y + 2, role, badge_fg); + } + + y += row_h + 4; + } + + // Separator + y += 8; + c.hline(x, y, content_w, colors::BORDER); + y += 16; + + // Status message + if (st->status_msg[0] && (montauk::get_milliseconds() - st->status_time < 3000)) { + c.text(x, y, st->status_msg, accent); + y += sfh + 8; + } + + // Action buttons + int btn_x = x; + + // Add User + c.fill_rounded_rect(btn_x, y, 90, USER_BTN_H, 4, accent); + { + int tw = text_width("Add User"); + c.text(btn_x + (90 - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Add User", colors::WHITE); + } + btn_x += 98; + + // Change Password (disabled when no selection) + { + bool enabled = st->selected_user >= 0; + Color bg = enabled ? accent : Color::from_rgb(0xCC, 0xCC, 0xCC); + c.fill_rounded_rect(btn_x, y, USER_BTN_W, USER_BTN_H, 4, bg); + int tw = text_width("Change Pwd"); + c.text(btn_x + (USER_BTN_W - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Change Pwd", colors::WHITE); + } + btn_x += USER_BTN_W + 8; + + // Delete (disabled when no selection) + { + bool enabled = st->selected_user >= 0; + Color del_bg = enabled ? Color::from_rgb(0xD0, 0x3E, 0x3E) : Color::from_rgb(0xCC, 0xCC, 0xCC); + c.fill_rounded_rect(btn_x, y, 70, USER_BTN_H, 4, del_bg); + int tw = text_width("Delete"); + c.text(btn_x + (70 - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Delete", colors::WHITE); + } +} + +// ============================================================================ +// Dialog helpers +// ============================================================================ + +static void dialog_append(char* buf, int* len, int max, char ch) { + if (*len < max - 1) { buf[*len] = ch; (*len)++; buf[*len] = '\0'; } +} +static void dialog_backspace(char* buf, int* len) { + if (*len > 0) { (*len)--; buf[*len] = '\0'; } +} + +static void dialog_close_self(DesktopState* ds, void* app_data) { + for (int i = 0; i < ds->window_count; i++) { + if (ds->windows[i].app_data == app_data) { + desktop_close_window(ds, i); + return; + } + } +} + +static void draw_input_field(Canvas& c, int x, int y, int w, int h, + const char* label, const char* value, + bool focused, bool masked, Color accent) { + int sfh = system_font_height(); + Color dim = Color::from_rgb(0x88, 0x88, 0x88); + + c.text(x, y, label, dim); + y += sfh + 2; + Color border = focused ? accent : colors::BORDER; + c.fill_rounded_rect(x, y, w, h, 3, Color::from_rgb(0xF5, 0xF5, 0xF5)); + c.rect(x, y, w, h, border); + + if (masked) { + int vlen = montauk::slen(value); + char dots[65]; + for (int i = 0; i < vlen && i < 64; i++) dots[i] = '*'; + dots[vlen < 64 ? vlen : 64] = '\0'; + c.text(x + 8, y + (h - sfh) / 2, dots, colors::TEXT_COLOR); + } else { + c.text(x + 8, y + (h - sfh) / 2, value, colors::TEXT_COLOR); + } + + if (focused) { + int tw = masked ? text_width("*") * montauk::slen(value) : text_width(value); + c.fill_rect(x + 8 + tw, y + 6, 2, h - 12, accent); + } +} + +// ============================================================================ +// Add User Dialog +// ============================================================================ + +struct AddUserDialogState { + DesktopState* ds; + SettingsState* parent; + Color accent; + int field; // 0=username, 1=display_name, 2=password + char username[32]; int username_len; + char display[64]; int display_len; + char password[64]; int password_len; + bool role_admin; + char error[64]; +}; + +static void adduser_on_draw(Window* win, Framebuffer& fb) { + AddUserDialogState* st = (AddUserDialogState*)win->app_data; + if (!st) return; + + Canvas c(win); + c.fill(colors::WINDOW_BG); + Color accent = st->accent; + int sfh = system_font_height(); + int pad = 16; + int fw = c.w - 2 * pad; + int y = pad; + + // Fields + draw_input_field(c, pad, y, fw, USER_FIELD_H, "Username", st->username, + st->field == 0, false, accent); + y += sfh + 2 + USER_FIELD_H + 10; + + draw_input_field(c, pad, y, fw, USER_FIELD_H, "Display Name", st->display, + st->field == 1, false, accent); + y += sfh + 2 + USER_FIELD_H + 10; + + draw_input_field(c, pad, y, fw, USER_FIELD_H, "Password", st->password, + st->field == 2, true, accent); + y += sfh + 2 + USER_FIELD_H + 12; + + // Role toggle + Color dim = Color::from_rgb(0x88, 0x88, 0x88); + c.text(pad, y + 4, "Role:", dim); + int rbx = pad + 60; + draw_toggle_btn(c, rbx, y, 60, USER_BTN_H, "User", !st->role_admin, accent); + draw_toggle_btn(c, rbx + 68, y, 60, USER_BTN_H, "Admin", st->role_admin, accent); + y += USER_BTN_H + 14; + + // Error message + if (st->error[0]) { + c.text(pad, y, st->error, Color::from_rgb(0xD0, 0x3E, 0x3E)); + y += sfh + 6; + } + + // Buttons at bottom + int btn_y = c.h - USER_BTN_H - pad; + c.fill_rounded_rect(pad, btn_y, 80, USER_BTN_H, 4, accent); + int tw = text_width("Create"); + c.text(pad + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Create", colors::WHITE); + + c.fill_rounded_rect(pad + 88, btn_y, 80, USER_BTN_H, 4, colors::WINDOW_BG); + c.rect(pad + 88, btn_y, 80, USER_BTN_H, colors::BORDER); + tw = text_width("Cancel"); + c.text(pad + 88 + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Cancel", colors::TEXT_COLOR); +} + +static void adduser_submit(AddUserDialogState* st) { + if (st->username_len == 0) { + montauk::strcpy(st->error, "Username is required"); + return; + } + if (st->password_len == 0) { + montauk::strcpy(st->error, "Password is required"); + return; + } + const char* dname = st->display_len > 0 ? st->display : st->username; + const char* role = st->role_admin ? "admin" : "user"; + if (montauk::user::create_user(st->username, dname, st->password, role)) { + st->parent->users_loaded = false; + montauk::strcpy(st->parent->status_msg, "User created"); + st->parent->status_time = montauk::get_milliseconds(); + dialog_close_self(st->ds, st); + } else { + montauk::strcpy(st->error, "Failed (username taken?)"); + } +} + +static void adduser_on_mouse(Window* win, MouseEvent& ev) { + AddUserDialogState* st = (AddUserDialogState*)win->app_data; + if (!st || !ev.left_pressed()) return; + + Rect cr = win->content_rect(); + int mx = ev.x - cr.x; + int my = ev.y - cr.y; + int pad = 16; + int sfh = system_font_height(); + int fw = win->content_w - 2 * pad; + int y = pad; + + // Username field hit + y += sfh + 2; + if (my >= y && my < y + USER_FIELD_H) { st->field = 0; return; } + y += USER_FIELD_H + 10; + + // Display field hit + y += sfh + 2; + if (my >= y && my < y + USER_FIELD_H) { st->field = 1; return; } + y += USER_FIELD_H + 10; + + // Password field hit + y += sfh + 2; + if (my >= y && my < y + USER_FIELD_H) { st->field = 2; return; } + y += USER_FIELD_H + 12; + + // Role toggle + int rbx = pad + 60; + if (mx >= rbx && mx < rbx + 60 && my >= y && my < y + USER_BTN_H) { + st->role_admin = false; return; + } + if (mx >= rbx + 68 && mx < rbx + 128 && my >= y && my < y + USER_BTN_H) { + st->role_admin = true; return; + } + + // Bottom buttons + int btn_y = win->content_h - USER_BTN_H - pad; + if (my >= btn_y && my < btn_y + USER_BTN_H) { + if (mx >= pad && mx < pad + 80) { adduser_submit(st); return; } + if (mx >= pad + 88 && mx < pad + 168) { dialog_close_self(st->ds, st); return; } + } +} + +static void adduser_on_key(Window* win, const Montauk::KeyEvent& key) { + AddUserDialogState* st = (AddUserDialogState*)win->app_data; + if (!st || !key.pressed) return; + + if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) { + adduser_submit(st); return; + } + if (key.scancode == 0x01) { dialog_close_self(st->ds, st); return; } + if (key.scancode == 0x0F) { st->field = (st->field + 1) % 3; return; } + if (key.ascii == '\b' || key.scancode == 0x0E) { + switch (st->field) { + case 0: dialog_backspace(st->username, &st->username_len); break; + case 1: dialog_backspace(st->display, &st->display_len); break; + case 2: dialog_backspace(st->password, &st->password_len); break; + } + return; + } + if (key.ascii >= 0x20 && key.ascii < 0x7F) { + switch (st->field) { + case 0: dialog_append(st->username, &st->username_len, 31, key.ascii); break; + case 1: dialog_append(st->display, &st->display_len, 63, key.ascii); break; + case 2: dialog_append(st->password, &st->password_len, 63, key.ascii); break; + } + } +} + +static void adduser_on_close(Window* win) { + if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; } +} + +static void open_add_user_dialog(SettingsState* parent) { + DesktopState* ds = parent->desktop; + int w = 340, h = 340; + int wx = (ds->screen_w - w) / 2; + int wy = (ds->screen_h - h) / 2; + int idx = desktop_create_window(ds, "Add User", wx, wy, w, h); + if (idx < 0) return; + + Window* win = &ds->windows[idx]; + AddUserDialogState* st = (AddUserDialogState*)montauk::malloc(sizeof(AddUserDialogState)); + montauk::memset(st, 0, sizeof(AddUserDialogState)); + st->ds = ds; + st->parent = parent; + st->accent = ds->settings.accent_color; + + win->app_data = st; + win->on_draw = adduser_on_draw; + win->on_mouse = adduser_on_mouse; + win->on_key = adduser_on_key; + win->on_close = adduser_on_close; +} + +// ============================================================================ +// Change Password Dialog +// ============================================================================ + +struct ChPwdDialogState { + DesktopState* ds; + SettingsState* parent; + Color accent; + char username[32]; + char display_name[64]; + int field; // 0=new, 1=confirm + char new_pwd[64]; int new_len; + char confirm[64]; int confirm_len; + char error[64]; +}; + +static void chpwd_on_draw(Window* win, Framebuffer& fb) { + ChPwdDialogState* st = (ChPwdDialogState*)win->app_data; + if (!st) return; + + Canvas c(win); + c.fill(colors::WINDOW_BG); + Color accent = st->accent; + int sfh = system_font_height(); + int pad = 16; + int fw = c.w - 2 * pad; + int y = pad; + + // Title + char title[80]; + snprintf(title, sizeof(title), "Change password for %s", st->display_name); + c.text(pad, y, title, colors::TEXT_COLOR); + y += sfh + 12; + + draw_input_field(c, pad, y, fw, USER_FIELD_H, "New Password", st->new_pwd, + st->field == 0, true, accent); + y += sfh + 2 + USER_FIELD_H + 10; + + draw_input_field(c, pad, y, fw, USER_FIELD_H, "Confirm Password", st->confirm, + st->field == 1, true, accent); + y += sfh + 2 + USER_FIELD_H + 12; + + // Error + if (st->error[0]) { + c.text(pad, y, st->error, Color::from_rgb(0xD0, 0x3E, 0x3E)); + } + + // Buttons at bottom + int btn_y = c.h - USER_BTN_H - pad; + c.fill_rounded_rect(pad, btn_y, 80, USER_BTN_H, 4, accent); + int tw = text_width("Save"); + c.text(pad + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Save", colors::WHITE); + + c.fill_rounded_rect(pad + 88, btn_y, 80, USER_BTN_H, 4, colors::WINDOW_BG); + c.rect(pad + 88, btn_y, 80, USER_BTN_H, colors::BORDER); + tw = text_width("Cancel"); + c.text(pad + 88 + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Cancel", colors::TEXT_COLOR); +} + +static void chpwd_submit(ChPwdDialogState* st) { + if (st->new_len == 0) { + montauk::strcpy(st->error, "Password cannot be empty"); + return; + } + if (!montauk::streq(st->new_pwd, st->confirm)) { + montauk::strcpy(st->error, "Passwords don't match"); + return; + } + montauk::user::change_password(st->username, st->new_pwd); + montauk::strcpy(st->parent->status_msg, "Password changed"); + st->parent->status_time = montauk::get_milliseconds(); + dialog_close_self(st->ds, st); +} + +static void chpwd_on_mouse(Window* win, MouseEvent& ev) { + ChPwdDialogState* st = (ChPwdDialogState*)win->app_data; + if (!st || !ev.left_pressed()) return; + + Rect cr = win->content_rect(); + int mx = ev.x - cr.x; + int my = ev.y - cr.y; + int pad = 16; + int sfh = system_font_height(); + int y = pad + sfh + 12; + + // New password field + y += sfh + 2; + if (my >= y && my < y + USER_FIELD_H) { st->field = 0; return; } + y += USER_FIELD_H + 10; + + // Confirm field + y += sfh + 2; + if (my >= y && my < y + USER_FIELD_H) { st->field = 1; return; } + + // Bottom buttons + int btn_y = win->content_h - USER_BTN_H - pad; + if (my >= btn_y && my < btn_y + USER_BTN_H) { + if (mx >= pad && mx < pad + 80) { chpwd_submit(st); return; } + if (mx >= pad + 88 && mx < pad + 168) { dialog_close_self(st->ds, st); return; } + } +} + +static void chpwd_on_key(Window* win, const Montauk::KeyEvent& key) { + ChPwdDialogState* st = (ChPwdDialogState*)win->app_data; + if (!st || !key.pressed) return; + + if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) { + chpwd_submit(st); return; + } + if (key.scancode == 0x01) { dialog_close_self(st->ds, st); return; } + if (key.scancode == 0x0F) { st->field = (st->field + 1) % 2; return; } + if (key.ascii == '\b' || key.scancode == 0x0E) { + if (st->field == 0) dialog_backspace(st->new_pwd, &st->new_len); + else dialog_backspace(st->confirm, &st->confirm_len); + return; + } + if (key.ascii >= 0x20 && key.ascii < 0x7F) { + if (st->field == 0) dialog_append(st->new_pwd, &st->new_len, 63, key.ascii); + else dialog_append(st->confirm, &st->confirm_len, 63, key.ascii); + } +} + +static void chpwd_on_close(Window* win) { + if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; } +} + +static void open_change_pwd_dialog(SettingsState* parent) { + if (parent->selected_user < 0) return; + DesktopState* ds = parent->desktop; + int w = 340, h = 260; + int wx = (ds->screen_w - w) / 2; + int wy = (ds->screen_h - h) / 2; + int idx = desktop_create_window(ds, "Change Password", wx, wy, w, h); + if (idx < 0) return; + + Window* win = &ds->windows[idx]; + ChPwdDialogState* st = (ChPwdDialogState*)montauk::malloc(sizeof(ChPwdDialogState)); + montauk::memset(st, 0, sizeof(ChPwdDialogState)); + st->ds = ds; + st->parent = parent; + st->accent = ds->settings.accent_color; + montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31); + montauk::strncpy(st->display_name, parent->users[parent->selected_user].display_name, 63); + + win->app_data = st; + win->on_draw = chpwd_on_draw; + win->on_mouse = chpwd_on_mouse; + win->on_key = chpwd_on_key; + win->on_close = chpwd_on_close; +} + +// ============================================================================ +// Delete User Dialog +// ============================================================================ + +struct DeleteUserDialogState { + DesktopState* ds; + SettingsState* parent; + char username[32]; + bool hover_delete, hover_cancel; +}; + +static void deluser_on_draw(Window* win, Framebuffer& fb) { + DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data; + if (!st) return; + + Canvas c(win); + c.fill(colors::WINDOW_BG); + int sfh = system_font_height(); + + char msg[96]; + snprintf(msg, sizeof(msg), "Delete user \"%s\"?", st->username); + int tw = text_width(msg); + c.text((c.w - tw) / 2, 24, msg, colors::TEXT_COLOR); + + const char* warn = "This action cannot be undone."; + tw = text_width(warn); + c.text((c.w - tw) / 2, 24 + sfh + 8, warn, Color::from_rgb(0x88, 0x88, 0x88)); + + // Buttons + int btn_w = 100, btn_h = 32; + int btn_y = c.h - btn_h - 20; + int gap = 20; + int total = btn_w * 2 + gap; + int bx = (c.w - total) / 2; + + Color del_bg = st->hover_delete + ? Color::from_rgb(0xDD, 0x44, 0x44) + : Color::from_rgb(0xD0, 0x3E, 0x3E); + c.button(bx, btn_y, btn_w, btn_h, "Delete", del_bg, colors::WHITE, 4); + + Color cancel_bg = st->hover_cancel + ? Color::from_rgb(0x99, 0x99, 0x99) + : Color::from_rgb(0x88, 0x88, 0x88); + c.button(bx + btn_w + gap, btn_y, btn_w, btn_h, "Cancel", cancel_bg, colors::WHITE, 4); +} + +static void deluser_on_mouse(Window* win, MouseEvent& ev) { + DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data; + if (!st) return; + + Rect cr = win->content_rect(); + int lx = ev.x - cr.x; + int ly = ev.y - cr.y; + + int btn_w = 100, btn_h = 32; + int btn_y = win->content_h - btn_h - 20; + int gap = 20; + int total = btn_w * 2 + gap; + int bx = (win->content_w - total) / 2; + + Rect db = {bx, btn_y, btn_w, btn_h}; + Rect cb = {bx + btn_w + gap, btn_y, btn_w, btn_h}; + st->hover_delete = db.contains(lx, ly); + st->hover_cancel = cb.contains(lx, ly); + + if (ev.left_pressed()) { + if (st->hover_delete) { + montauk::user::delete_user(st->username); + st->parent->users_loaded = false; + st->parent->selected_user = -1; + montauk::strcpy(st->parent->status_msg, "User deleted"); + st->parent->status_time = montauk::get_milliseconds(); + dialog_close_self(st->ds, st); + return; + } + if (st->hover_cancel) { + dialog_close_self(st->ds, st); + return; + } + } +} + +static void deluser_on_key(Window* win, const Montauk::KeyEvent& key) { + DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data; + if (!st || !key.pressed) return; + + if (key.ascii == '\n' || key.ascii == '\r') { + montauk::user::delete_user(st->username); + st->parent->users_loaded = false; + st->parent->selected_user = -1; + montauk::strcpy(st->parent->status_msg, "User deleted"); + st->parent->status_time = montauk::get_milliseconds(); + dialog_close_self(st->ds, st); + } + if (key.scancode == 0x01) { + dialog_close_self(st->ds, st); + } +} + +static void deluser_on_close(Window* win) { + if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; } +} + +static void open_delete_user_dialog(SettingsState* parent) { + if (parent->selected_user < 0) return; + DesktopState* ds = parent->desktop; + + // Don't allow deleting yourself + if (montauk::streq(parent->users[parent->selected_user].username, ds->current_user)) { + montauk::strcpy(parent->status_msg, "Cannot delete current user"); + parent->status_time = montauk::get_milliseconds(); + return; + } + + int w = 300, h = 150; + int wx = (ds->screen_w - w) / 2; + int wy = (ds->screen_h - h) / 2; + int idx = desktop_create_window(ds, "Delete User", wx, wy, w, h); + if (idx < 0) return; + + Window* win = &ds->windows[idx]; + DeleteUserDialogState* st = (DeleteUserDialogState*)montauk::malloc(sizeof(DeleteUserDialogState)); + montauk::memset(st, 0, sizeof(DeleteUserDialogState)); + st->ds = ds; + st->parent = parent; + montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31); + + win->app_data = st; + win->on_draw = deluser_on_draw; + win->on_mouse = deluser_on_mouse; + win->on_key = deluser_on_key; + win->on_close = deluser_on_close; +} + static void settings_on_draw(Window* win, Framebuffer& fb) { SettingsState* st = (SettingsState*)win->app_data; if (!st) return; @@ -372,7 +1080,8 @@ static void settings_on_draw(Window* win, Framebuffer& fb) { switch (st->active_tab) { case 0: settings_draw_appearance(content, st); break; case 1: settings_draw_display(content, st); break; - case 2: settings_draw_about(content, st); break; + case 2: settings_draw_users(content, st); break; + case 3: settings_draw_about(content, st); break; } } @@ -432,12 +1141,14 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { if (mx >= x && mx < x + 100 && cy >= y && cy < y + 16) { s.bg_gradient = true; s.bg_image = false; + settings_persist(st); return; } // Radio: Solid if (mx >= x + 120 && mx < x + 210 && cy >= y && cy < y + 16) { s.bg_gradient = false; s.bg_image = false; + settings_persist(st); return; } // Radio: Image @@ -445,16 +1156,17 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { s.bg_image = true; s.bg_gradient = false; if (!st->wp_scanned) { - wallpaper_scan_dir("0:/home", &st->wp_files); + wallpaper_scan_dir(st->desktop->home_dir, &st->wp_files); st->wp_scanned = true; } + settings_persist(st); return; } y += line_h + 4; int idx; if (mode_image) { - // "Images in 0:/home/" label + // Wallpaper file list y += sfh + 6; // File list clicks @@ -463,10 +1175,12 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { mx >= x && mx < win->content_w - x) { // Build full path and load wallpaper char fullpath[256]; - montauk::strcpy(fullpath, "0:/home/"); + montauk::strcpy(fullpath, st->desktop->home_dir); + str_append(fullpath, "/", 256); str_append(fullpath, st->wp_files.names[i], 256); wallpaper_load(&s, fullpath, st->desktop->screen_w, st->desktop->screen_h); + settings_persist(st); return; } y += WP_ITEM_H; @@ -477,6 +1191,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Top swatches if (swatch_hit(mx, cy, x + 70, y, &idx)) { s.bg_grad_top = bg_palette[idx]; + settings_persist(st); return; } y += SWATCH_SIZE + 14; @@ -484,6 +1199,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Bottom swatches if (swatch_hit(mx, cy, x + 70, y, &idx)) { s.bg_grad_bottom = bg_palette[idx]; + settings_persist(st); return; } y += SWATCH_SIZE + 14; @@ -491,6 +1207,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Solid color swatches if (swatch_hit(mx, cy, x + 70, y, &idx)) { s.bg_solid = bg_palette[idx]; + settings_persist(st); return; } y += SWATCH_SIZE + 14; @@ -502,6 +1219,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Panel color swatches if (swatch_hit(mx, cy, x + 110, y, &idx)) { s.panel_color = panel_palette[idx]; + settings_persist(st); return; } y += SWATCH_SIZE + 14; @@ -512,6 +1230,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Accent color swatches if (swatch_hit(mx, cy, x + 110, y, &idx)) { s.accent_color = accent_palette[idx]; + settings_persist(st); return; } } else if (st->active_tab == 1) { @@ -525,11 +1244,13 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Window Shadows: On if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) { s.show_shadows = true; + settings_persist(st); return; } // Window Shadows: Off if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) { s.show_shadows = false; + settings_persist(st); return; } y += btn_h + 20 + 16; @@ -537,11 +1258,13 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { // Clock: 24h if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) { s.clock_24h = true; + settings_persist(st); return; } // Clock: 12h if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) { s.clock_24h = false; + settings_persist(st); return; } y += btn_h + 20 + 16; @@ -553,6 +1276,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { s.ui_scale = 0; apply_ui_scale(0); montauk::win_setscale(0); + settings_persist(st); return; } // Default @@ -560,6 +1284,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { s.ui_scale = 1; apply_ui_scale(1); montauk::win_setscale(1); + settings_persist(st); return; } // Large @@ -567,11 +1292,71 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) { s.ui_scale = 2; apply_ui_scale(2); montauk::win_setscale(2); + settings_persist(st); + return; + } + } else if (st->active_tab == 2) { + // Users tab + if (!st->desktop->is_admin) return; + + int x = 16; + int sfh = system_font_height(); + int y = 20; + int content_w = win->content_w - 2 * x; + int row_h = user_row_height(); + + // User list rows + for (int i = 0; i < st->user_count; i++) { + if (cy >= y && cy < y + row_h && mx >= x && mx < x + content_w) { + st->selected_user = (st->selected_user == i) ? -1 : i; + return; + } + y += row_h + 4; + } + + // Separator + gap + y += 8 + 1 + 16; + + // Status message (if shown, takes space) + if (st->status_msg[0] && (montauk::get_milliseconds() - st->status_time < 3000)) { + y += sfh + 8; + } + + // Action buttons + int btn_x = x; + + // Add User + if (mx >= btn_x && mx < btn_x + 90 && cy >= y && cy < y + USER_BTN_H) { + open_add_user_dialog(st); + return; + } + btn_x += 98; + + // Change Password + if (mx >= btn_x && mx < btn_x + USER_BTN_W && cy >= y && cy < y + USER_BTN_H) { + if (st->selected_user >= 0) open_change_pwd_dialog(st); + return; + } + btn_x += USER_BTN_W + 8; + + // Delete + if (mx >= btn_x && mx < btn_x + 70 && cy >= y && cy < y + USER_BTN_H) { + if (st->selected_user >= 0) open_delete_user_dialog(st); return; } } } +// ============================================================================ +// Keyboard +// ============================================================================ + +static void settings_on_key(Window* win, const Montauk::KeyEvent& key) { + // Settings main window no longer needs keyboard handling — + // text input is handled by dialog windows. + (void)win; (void)key; +} + // ============================================================================ // Cleanup // ============================================================================ @@ -600,9 +1385,13 @@ void open_settings(DesktopState* ds) { st->uptime_ms = montauk::get_milliseconds(); st->wp_scanned = false; st->wp_files.count = 0; + st->selected_user = -1; + st->users_loaded = false; + st->status_msg[0] = '\0'; win->app_data = st; win->on_draw = settings_on_draw; win->on_mouse = settings_on_mouse; + win->on_key = settings_on_key; win->on_close = settings_on_close; } diff --git a/programs/src/desktop/compose.cpp b/programs/src/desktop/compose.cpp index 3f9a0db..15933c5 100644 --- a/programs/src/desktop/compose.cpp +++ b/programs/src/desktop/compose.cpp @@ -6,6 +6,149 @@ #include "desktop_internal.hpp" +// ============================================================================ +// Lock Screen Drawing +// ============================================================================ + +static constexpr Color LOCK_CARD_BG = Color::from_rgb(0xFF, 0xFF, 0xFF); +static constexpr Color LOCK_FIELD_BG = Color::from_rgb(0xF5, 0xF5, 0xF5); +static constexpr Color LOCK_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC); +static constexpr Color LOCK_ACCENT = Color::from_rgb(0x36, 0x7B, 0xF0); +static constexpr Color LOCK_TEXT = Color::from_rgb(0x33, 0x33, 0x33); +static constexpr Color LOCK_DIM = Color::from_rgb(0x66, 0x66, 0x66); +static constexpr Color LOCK_ERROR = Color::from_rgb(0xE0, 0x40, 0x40); +static constexpr Color LOCK_BTN_TEXT = Color::from_rgb(0xFF, 0xFF, 0xFF); +static constexpr int LOCK_CARD_W = 360; +static constexpr int LOCK_FIELD_H = 36; +static constexpr int LOCK_BTN_H = 40; + +void desktop_draw_lock_screen(DesktopState* ds) { + Framebuffer& fb = ds->fb; + int sw = ds->screen_w; + int sh = ds->screen_h; + int sfh = system_font_height(); + + // Dark overlay on top of background + fb.fill_rect_alpha(0, 0, sw, sh, Color::from_rgba(0, 0, 0, 0x80)); + + // Clock display above card + Montauk::DateTime dt; + montauk::gettime(&dt); + char time_str[12]; + snprintf(time_str, sizeof(time_str), "%02d:%02d", (int)dt.Hour, (int)dt.Minute); + + // Calculate card dimensions + int error_h = ds->lock_show_error ? sfh + 8 : 0; + int card_h = 20 + sfh + 16 + sfh + 12 + sfh + 4 + LOCK_FIELD_H + 16 + LOCK_BTN_H + error_h + 20; + int card_x = (sw - LOCK_CARD_W) / 2; + int card_y = (sh - card_h) / 2; + + // Draw time above card + int time_w = text_width(time_str); + draw_text(fb, (sw - time_w) / 2, card_y - sfh * 3, time_str, Color::from_rgb(0xFF, 0xFF, 0xFF)); + + // Date below time + { + int month_idx = dt.Month > 0 && dt.Month <= 12 ? dt.Month - 1 : 0; + char date_str[32]; + snprintf(date_str, sizeof(date_str), "%s %d", month_names[month_idx], (int)dt.Day); + int dw = text_width(date_str); + draw_text(fb, (sw - dw) / 2, card_y - sfh * 2 + 4, date_str, Color::from_rgb(0xCC, 0xCC, 0xCC)); + } + + // Card background with rounded corners + fill_rounded_rect(fb, card_x, card_y, LOCK_CARD_W, card_h, 12, LOCK_CARD_BG); + + int x = card_x + 24; + int content_w = LOCK_CARD_W - 48; + int y = card_y + 20; + + // Title (with optional lock icon beside it) + { + const char* title = "Locked"; + int tw = text_width(title); + int icon_w = ds->icon_lock.pixels ? 20 : 0; + int gap = icon_w ? 8 : 0; + int total = icon_w + gap + tw; + int tx = card_x + (LOCK_CARD_W - total) / 2; + + if (ds->icon_lock.pixels) { + fb.blit_alpha(tx, y + (sfh - 20) / 2, ds->icon_lock.width, ds->icon_lock.height, ds->icon_lock.pixels); + } + draw_text(fb, tx + icon_w + gap, y, title, LOCK_TEXT); + y += sfh + 16; + } + + // Username display (cached at lock time) + { + int nw = text_width(ds->lock_display_name); + draw_text(fb, card_x + (LOCK_CARD_W - nw) / 2, y, ds->lock_display_name, LOCK_DIM); + y += sfh + 12; + } + + // Password label + draw_text(fb, x, y, "Password", LOCK_DIM); + y += sfh + 4; + + // Password field + { + fb.fill_rect(x, y, content_w, LOCK_FIELD_H, LOCK_FIELD_BG); + + // 2px accent border (always active) + for (int i = 0; i < content_w; i++) { fb.put_pixel(x + i, y, LOCK_ACCENT); fb.put_pixel(x + i, y + 1, LOCK_ACCENT); } + for (int i = 0; i < content_w; i++) { fb.put_pixel(x + i, y + LOCK_FIELD_H - 1, LOCK_ACCENT); fb.put_pixel(x + i, y + LOCK_FIELD_H - 2, LOCK_ACCENT); } + for (int i = 0; i < LOCK_FIELD_H; i++) { fb.put_pixel(x, y + i, LOCK_ACCENT); fb.put_pixel(x + 1, y + i, LOCK_ACCENT); } + for (int i = 0; i < LOCK_FIELD_H; i++) { fb.put_pixel(x + content_w - 1, y + i, LOCK_ACCENT); fb.put_pixel(x + content_w - 2, y + i, LOCK_ACCENT); } + + // Masked password text (clipped to field width) + char masked[65]; + int len = ds->lock_password_len; + if (len > 64) len = 64; + int max_text_w = content_w - 10 - 10 - 2; // left pad, right pad, cursor + // Show only the trailing portion that fits + int vis = len; + { + char tmp[65]; + for (int i = 0; i < len; i++) tmp[i] = '*'; + tmp[len] = '\0'; + while (vis > 0 && text_width(tmp + (len - vis)) > max_text_w) + vis--; + } + for (int i = 0; i < vis; i++) masked[i] = '*'; + masked[vis] = '\0'; + + int ty = y + (LOCK_FIELD_H - sfh) / 2; + draw_text(fb, x + 10, ty, masked, LOCK_TEXT); + + // Cursor + int cx = x + 10 + text_width(masked); + fb.fill_rect(cx, ty, 2, sfh, LOCK_ACCENT); + + y += LOCK_FIELD_H + 16; + } + + // Unlock button + { + fill_rounded_rect(fb, x, y, content_w, LOCK_BTN_H, 6, LOCK_ACCENT); + const char* label = "Unlock"; + int tw = text_width(label); + int ty = y + (LOCK_BTN_H - sfh) / 2; + draw_text(fb, x + (content_w - tw) / 2, ty, label, LOCK_BTN_TEXT); + y += LOCK_BTN_H; + } + + // Error message + if (ds->lock_show_error) { + y += 8; + int ew = text_width(ds->lock_error); + draw_text(fb, card_x + (LOCK_CARD_W - ew) / 2, y, ds->lock_error, LOCK_ERROR); + } +} + +// ============================================================================ +// Desktop Composition +// ============================================================================ + void gui::desktop_compose(DesktopState* ds) { Framebuffer& fb = ds->fb; @@ -45,6 +188,13 @@ void gui::desktop_compose(DesktopState* ds) { } } + // Lock screen: draw overlay and card, then cursor, and return early + if (ds->screen_locked) { + desktop_draw_lock_screen(ds); + draw_cursor(fb, ds->mouse.x, ds->mouse.y); + return; + } + // Draw windows from bottom to top for (int i = 0; i < ds->window_count; i++) { if (ds->windows[i].state != WIN_MINIMIZED && ds->windows[i].state != WIN_CLOSED) { @@ -65,6 +215,11 @@ void gui::desktop_compose(DesktopState* ds) { desktop_draw_net_popup(ds); } + // Draw volume popup if open + if (ds->vol_popup_open) { + desktop_draw_vol_popup(ds); + } + // Draw right-click context menu if open if (ds->ctx_menu_open) { static constexpr int CTX_MENU_W = 180; diff --git a/programs/src/desktop/desktop_internal.hpp b/programs/src/desktop/desktop_internal.hpp index c17e133..37db940 100644 --- a/programs/src/desktop/desktop_internal.hpp +++ b/programs/src/desktop/desktop_internal.hpp @@ -115,6 +115,10 @@ gui::CursorStyle cursor_for_edge(gui::ResizeEdge edge); // panel.cpp void desktop_draw_app_menu(gui::DesktopState* ds); void desktop_draw_net_popup(gui::DesktopState* ds); +void desktop_draw_vol_popup(gui::DesktopState* ds); + +// compose.cpp +void desktop_draw_lock_screen(gui::DesktopState* ds); // main.cpp void desktop_scan_apps(gui::DesktopState* ds); diff --git a/programs/src/desktop/input.cpp b/programs/src/desktop/input.cpp index 7be5f53..197d070 100644 --- a/programs/src/desktop/input.cpp +++ b/programs/src/desktop/input.cpp @@ -5,8 +5,133 @@ */ #include "desktop_internal.hpp" +#include + +// ============================================================================ +// Lock Screen Input +// ============================================================================ + +static void lock_screen(DesktopState* ds) { + ds->screen_locked = true; + ds->lock_password[0] = '\0'; + ds->lock_password_len = 0; + ds->lock_error[0] = '\0'; + ds->lock_show_error = false; + ds->app_menu_open = false; + ds->ctx_menu_open = false; + ds->net_popup_open = false; + ds->vol_popup_open = false; + + // Cache display name for lock screen rendering + montauk::strncpy(ds->lock_display_name, ds->current_user, sizeof(ds->lock_display_name)); + montauk::user::UserInfo users[16]; + int count = montauk::user::load_users(users, 16); + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, ds->current_user)) { + if (users[i].display_name[0]) + montauk::strncpy(ds->lock_display_name, users[i].display_name, sizeof(ds->lock_display_name)); + break; + } + } +} + +static bool try_unlock(DesktopState* ds) { + ds->lock_show_error = false; + + if (montauk::user::authenticate(ds->current_user, ds->lock_password)) { + ds->screen_locked = false; + ds->lock_password[0] = '\0'; + ds->lock_password_len = 0; + return true; + } + + montauk::strcpy(ds->lock_error, "Incorrect password"); + ds->lock_show_error = true; + ds->lock_password[0] = '\0'; + ds->lock_password_len = 0; + return false; +} + +static void handle_lock_mouse(DesktopState* ds) { + int mx = ds->mouse.x; + int my = ds->mouse.y; + uint8_t buttons = ds->mouse.buttons; + uint8_t prev = ds->prev_buttons; + bool left_pressed = (buttons & 0x01) && !(prev & 0x01); + + if (!left_pressed) return; + + int sfh = system_font_height(); + int card_w = 360; + int content_w = card_w - 48; + int field_h = 36; + int btn_h = 40; + + // Calculate card layout to find button position + int error_h = ds->lock_show_error ? sfh + 8 : 0; + int card_h = 20 + sfh + 16 + sfh + 12 + sfh + 4 + field_h + 16 + btn_h + error_h + 20; + int card_x = (ds->screen_w - card_w) / 2; + int card_y = (ds->screen_h - card_h) / 2; + int x = card_x + 24; + + // Walk through the layout to find the Unlock button y position + int y = card_y + 20; + y += sfh + 16; // title + y += sfh + 12; // username + y += sfh + 4; // "Password" label + y += field_h + 16; // field + gap + + // Check Unlock button + if (mx >= x && mx < x + content_w && my >= y && my < y + btn_h) { + try_unlock(ds); + return; + } + + // Check password field click (just keep focus, nothing else to switch to) + int field_y = y - field_h - 16; + if (mx >= x && mx < x + content_w && my >= field_y && my < field_y + field_h) { + ds->lock_show_error = false; + } +} + +static void handle_lock_keyboard(DesktopState* ds, const Montauk::KeyEvent& key) { + if (!key.pressed) return; + + // Enter submits + if (key.ascii == '\n' || key.ascii == '\r') { + try_unlock(ds); + return; + } + + // Backspace + if (key.ascii == '\b' || key.scancode == 0x0E) { + if (ds->lock_password_len > 0) { + ds->lock_password_len--; + ds->lock_password[ds->lock_password_len] = '\0'; + } + return; + } + + // Printable characters + if (key.ascii >= 0x20 && key.ascii < 0x7F) { + if (ds->lock_password_len < 63) { + ds->lock_password[ds->lock_password_len] = key.ascii; + ds->lock_password_len++; + ds->lock_password[ds->lock_password_len] = '\0'; + } + } +} + +// ============================================================================ +// Desktop Mouse Handling +// ============================================================================ void gui::desktop_handle_mouse(DesktopState* ds) { + if (ds->screen_locked) { + handle_lock_mouse(ds); + return; + } + int mx = ds->mouse.x; int my = ds->mouse.y; uint8_t buttons = ds->mouse.buttons; @@ -213,8 +338,8 @@ void gui::desktop_handle_mouse(DesktopState* ds) { menu_cat_expanded[cur_cat] = !menu_cat_expanded[cur_cat]; } else if (!row.is_category) { if (row.external) { - // Launch external app from manifest - montauk::spawn(row.binary_path); + // Launch external app with user's home dir + montauk::spawn(row.binary_path, ds->home_dir); } else { // Dispatch embedded app switch (row.app_id) { @@ -230,6 +355,8 @@ void gui::desktop_handle_mouse(DesktopState* ds) { case 12: open_reboot_dialog(ds); break; case 14: open_shutdown_dialog(ds); break; case 15: open_wordprocessor(ds); break; + case 16: montauk::exit(0); break; // Log Out + case 17: lock_screen(ds); break; // Lock Screen } } ds->app_menu_open = false; @@ -244,10 +371,104 @@ void gui::desktop_handle_mouse(DesktopState* ds) { } } + // Handle volume popup interaction + if (ds->vol_popup_open) { + int popup_x = ds->vol_icon_rect.x + ds->vol_icon_rect.w - 200; + int popup_y = PANEL_HEIGHT + 2; + if (popup_x < 4) popup_x = 4; + Rect vol_rect = {popup_x, popup_y, 200, 120}; + + // Handle drag continuity + if (ds->vol_dragging) { + if (left_held) { + int slider_abs_x = popup_x + 16; + int v = ((mx - slider_abs_x) * 100) / (200 - 32); + if (v < 0) v = 0; + if (v > 100) v = 100; + ds->vol_muted = false; + ds->vol_level = v; + montauk::audio_set_volume(0, v); + return; + } + if (left_released) { + ds->vol_dragging = false; + } + } + + if (left_pressed) { + if (vol_rect.contains(mx, my)) { + // Slider area (y = popup_y + 56, height = 8, with generous hit zone) + int slider_abs_x = popup_x + 16; + int slider_abs_y = popup_y + 56; + int slider_w = 200 - 32; + if (my >= slider_abs_y - 10 && my <= slider_abs_y + 8 + 10 && + mx >= slider_abs_x - 8 && mx <= slider_abs_x + slider_w + 8) { + int v = ((mx - slider_abs_x) * 100) / slider_w; + if (v < 0) v = 0; + if (v > 100) v = 100; + ds->vol_muted = false; + ds->vol_level = v; + montauk::audio_set_volume(0, v); + ds->vol_dragging = true; + return; + } + + // Buttons (y = popup_y + 78, h = 24) + int btn_h = 24; + int btn_y = popup_y + 78; + int minus_w = 36, plus_w = 36, mute_w = 50, gap = 8; + int total_w = minus_w + plus_w + mute_w + gap * 2; + int bx = popup_x + (200 - total_w) / 2; + + if (my >= btn_y && my < btn_y + btn_h) { + // [-] + if (mx >= bx && mx < bx + minus_w) { + ds->vol_muted = false; + int v = ds->vol_level - 5; + if (v < 0) v = 0; + ds->vol_level = v; + montauk::audio_set_volume(0, v); + return; + } + bx += minus_w + gap; + // [+] + if (mx >= bx && mx < bx + plus_w) { + ds->vol_muted = false; + int v = ds->vol_level + 5; + if (v > 100) v = 100; + ds->vol_level = v; + montauk::audio_set_volume(0, v); + return; + } + bx += plus_w + gap; + // [Mute] + if (mx >= bx && mx < bx + mute_w) { + if (ds->vol_muted) { + ds->vol_muted = false; + montauk::audio_set_volume(0, ds->vol_pre_mute); + ds->vol_level = ds->vol_pre_mute; + } else { + ds->vol_pre_mute = ds->vol_level; + ds->vol_muted = true; + montauk::audio_set_volume(0, 0); + } + return; + } + } + return; // click inside popup but not on any control + } else if (!ds->vol_icon_rect.contains(mx, my)) { + ds->vol_popup_open = false; + ds->vol_dragging = false; + } + } + } + // Handle net popup clicks if (ds->net_popup_open && left_pressed) { int popup_w = 220; - int popup_h = 130; + int fh_net = system_font_height(); + int row_h_net = fh_net + 8; + int popup_h = (row_h_net + 8) + row_h_net * 5 + 12; int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w; int popup_y = PANEL_HEIGHT + 2; if (popup_x < 4) popup_x = 4; @@ -266,6 +487,17 @@ void gui::desktop_handle_mouse(DesktopState* ds) { if (mx < 36) { ds->app_menu_open = !ds->app_menu_open; ds->net_popup_open = false; + ds->vol_popup_open = false; + ds->ctx_menu_open = false; + return; + } + + // Volume icon + if (ds->vol_icon_rect.w > 0 && ds->vol_icon_rect.contains(mx, my)) { + ds->vol_popup_open = !ds->vol_popup_open; + ds->vol_dragging = false; + ds->app_menu_open = false; + ds->net_popup_open = false; ds->ctx_menu_open = false; return; } @@ -274,6 +506,7 @@ void gui::desktop_handle_mouse(DesktopState* ds) { if (ds->net_icon_rect.w > 0 && ds->net_icon_rect.contains(mx, my)) { ds->net_popup_open = !ds->net_popup_open; ds->app_menu_open = false; + ds->vol_popup_open = false; ds->ctx_menu_open = false; return; } @@ -369,11 +602,6 @@ void gui::desktop_handle_mouse(DesktopState* ds) { if (win->state != WIN_MAXIMIZED) { ResizeEdge edge = hit_test_resize_edge(win->frame, mx, my); if (edge != RESIZE_NONE) { - win->resizing = true; - win->resize_edge = edge; - win->resize_start_frame = win->frame; - win->resize_start_mx = mx; - win->resize_start_my = my; desktop_raise_window(ds, i); int new_idx = ds->window_count - 1; ds->windows[new_idx].resizing = true; @@ -388,9 +616,6 @@ void gui::desktop_handle_mouse(DesktopState* ds) { // Check titlebar (start drag) Rect tb = win->titlebar_rect(); if (tb.contains(mx, my)) { - win->dragging = true; - win->drag_offset_x = mx - win->frame.x; - win->drag_offset_y = my - win->frame.y; desktop_raise_window(ds, i); int new_idx = ds->window_count - 1; ds->windows[new_idx].dragging = true; @@ -433,6 +658,7 @@ void gui::desktop_handle_mouse(DesktopState* ds) { ds->app_menu_open = false; ds->ctx_menu_open = false; + ds->vol_popup_open = false; } // Forward continuous mouse events to focused window (hover, drag, release) @@ -499,13 +725,23 @@ void gui::desktop_handle_mouse(DesktopState* ds) { ds->ctx_menu_y = my; ds->app_menu_open = false; ds->net_popup_open = false; + ds->vol_popup_open = false; } } } void gui::desktop_handle_keyboard(DesktopState* ds, const Montauk::KeyEvent& key) { + if (ds->screen_locked) { + handle_lock_keyboard(ds, key); + return; + } + // Global shortcuts (only on key press) if (key.pressed && key.ctrl && key.alt) { + if (key.ascii == 'l' || key.ascii == 'L') { + lock_screen(ds); + return; + } if (key.ascii == 't' || key.ascii == 'T') { open_terminal(ds); return; diff --git a/programs/src/desktop/main.cpp b/programs/src/desktop/main.cpp index a1c271e..663115d 100644 --- a/programs/src/desktop/main.cpp +++ b/programs/src/desktop/main.cpp @@ -5,6 +5,8 @@ */ #include "desktop_internal.hpp" +#include +#include // ============================================================================ // App Manifest Scanning @@ -168,9 +170,11 @@ void desktop_build_menu(DesktopState* ds) { // Divider + always-visible entries menu_add_category(""); // divider (cat 4, always expanded) - menu_add_embedded("Settings", 11, &ds->icon_settings); - menu_add_embedded("Reboot", 12, &ds->icon_reboot); - menu_add_embedded("Shutdown", 14, &ds->icon_shutdown); + menu_add_embedded("Settings", 11, &ds->icon_settings); + menu_add_embedded("Lock Screen", 17, &ds->icon_lock); + menu_add_embedded("Log Out", 16, &ds->icon_logout); + menu_add_embedded("Reboot", 12, &ds->icon_reboot); + menu_add_embedded("Shutdown", 14, &ds->icon_shutdown); } // ============================================================================ @@ -224,9 +228,12 @@ void gui::desktop_init(DesktopState* ds) { ds->icon_settings = svg_load("0:/icons/help-about.svg", 20, 20, defColor); ds->icon_reboot = svg_load("0:/icons/system-reboot.svg", 20, 20, defColor); ds->icon_shutdown = svg_load("0:/icons/system-shutdown.svg", 20, 20, defColor); + ds->icon_logout = svg_load("0:/icons/gnome-logout.svg", 20, 20, defColor); ds->icon_procmgr = svg_load("0:/icons/system-monitor.svg", 20, 20, defColor); ds->icon_mandelbrot = svg_load("0:/icons/applications-science.svg", 20, 20, defColor); + ds->icon_volume = svg_load("0:/icons/audio-volume-high-symbolic.svg", 16, 16, colors::PANEL_TEXT); + ds->icon_lock = svg_load("0:/icons/lock.svg", 20, 20, defColor); // Scan 0:/apps/ for external app manifests and build the menu desktop_scan_apps(ds); @@ -248,10 +255,61 @@ void gui::desktop_init(DesktopState* ds) { ds->settings.clock_24h = true; ds->settings.ui_scale = 1; - // Try to load default wallpaper - wallpaper_load(&ds->settings, "0:/home/lucas-alexander-2dJn8XoIKCg-unsplash.jpg", - ds->screen_w, ds->screen_h); - montauk::win_setscale(1); + // Load per-user desktop settings + { + auto doc = montauk::config::load_user(ds->current_user, "desktop"); + + const char* wp = doc.get_string("wallpaper.path", ""); + if (wp[0] != '\0') { + wallpaper_load(&ds->settings, wp, ds->screen_w, ds->screen_h); + } else { + // Fall back to system-wide default wallpaper from 0:/config/desktop.toml + auto sys = montauk::config::load("desktop"); + const char* def_wp = sys.get_string("wallpaper.path", ""); + if (def_wp[0] != '\0') { + wallpaper_load(&ds->settings, def_wp, ds->screen_w, ds->screen_h); + } + sys.destroy(); + } + + // Restore other settings from user config + const char* bg_mode = doc.get_string("background.mode", ""); + if (montauk::streq(bg_mode, "solid")) { + ds->settings.bg_gradient = false; + ds->settings.bg_image = false; + } else if (montauk::streq(bg_mode, "gradient")) { + ds->settings.bg_gradient = true; + ds->settings.bg_image = false; + } + // (image mode is set by wallpaper_load above) + + // Background colors + int64_t solid = doc.get_int("background.solid_color", -1); + if (solid >= 0) ds->settings.bg_solid = Color::from_rgb( + (uint8_t)((solid >> 16) & 0xFF), (uint8_t)((solid >> 8) & 0xFF), (uint8_t)(solid & 0xFF)); + int64_t gtop = doc.get_int("background.grad_top", -1); + if (gtop >= 0) ds->settings.bg_grad_top = Color::from_rgb( + (uint8_t)((gtop >> 16) & 0xFF), (uint8_t)((gtop >> 8) & 0xFF), (uint8_t)(gtop & 0xFF)); + int64_t gbot = doc.get_int("background.grad_bottom", -1); + if (gbot >= 0) ds->settings.bg_grad_bottom = Color::from_rgb( + (uint8_t)((gbot >> 16) & 0xFF), (uint8_t)((gbot >> 8) & 0xFF), (uint8_t)(gbot & 0xFF)); + + // Appearance colors + int64_t panel = doc.get_int("appearance.panel_color", -1); + if (panel >= 0) ds->settings.panel_color = Color::from_rgb( + (uint8_t)((panel >> 16) & 0xFF), (uint8_t)((panel >> 8) & 0xFF), (uint8_t)(panel & 0xFF)); + int64_t accent = doc.get_int("appearance.accent_color", -1); + if (accent >= 0) ds->settings.accent_color = Color::from_rgb( + (uint8_t)((accent >> 16) & 0xFF), (uint8_t)((accent >> 8) & 0xFF), (uint8_t)(accent & 0xFF)); + + int64_t scale = doc.get_int("display.ui_scale", 1); + ds->settings.ui_scale = (int)scale; + ds->settings.clock_24h = doc.get_bool("display.clock_24h", true); + ds->settings.show_shadows = doc.get_bool("display.show_shadows", true); + + doc.destroy(); + } + montauk::win_setscale(ds->settings.ui_scale); ds->ctx_menu_open = false; ds->ctx_menu_x = 0; @@ -262,8 +320,22 @@ void gui::desktop_init(DesktopState* ds) { ds->net_cfg_last_poll = montauk::get_milliseconds(); ds->net_icon_rect = {0, 0, 0, 0}; + ds->vol_popup_open = false; + ds->vol_icon_rect = {0, 0, 0, 0}; + int vol = montauk::audio_get_volume(0); + ds->vol_level = vol >= 0 ? vol : 80; + ds->vol_muted = false; + ds->vol_pre_mute = ds->vol_level; + ds->vol_dragging = false; + ds->vol_last_poll = montauk::get_milliseconds(); + ds->closing_ext_count = 0; + ds->screen_locked = false; + ds->lock_password[0] = '\0'; + ds->lock_password_len = 0; + ds->lock_error[0] = '\0'; + ds->lock_show_error = false; } // ============================================================================ @@ -412,21 +484,25 @@ void gui::desktop_run(DesktopState* ds) { // Poll external windows (discover new, remove dead, update dirty) desktop_poll_external_windows(ds); - // Poll windows that have a poll callback - for (int i = 0; i < ds->window_count; i++) { - Window* win = &ds->windows[i]; - if (win->state == WIN_CLOSED) continue; - if (win->on_poll) { - win->on_poll(win); + if (!ds->screen_locked) { + // Poll windows that have a poll callback + for (int i = 0; i < ds->window_count; i++) { + Window* win = &ds->windows[i]; + if (win->state == WIN_CLOSED) continue; + if (win->on_poll) { + win->on_poll(win); + } } } // Handle mouse events desktop_handle_mouse(ds); - // Re-poll external windows so that any killed during mouse/key - // handling are removed before we touch their pixel buffers. - desktop_poll_external_windows(ds); + if (!ds->screen_locked) { + // Re-poll external windows so that any killed during mouse/key + // handling are removed before we touch their pixel buffers. + desktop_poll_external_windows(ds); + } // Compose and present desktop_compose(ds); @@ -450,6 +526,31 @@ extern "C" void _start() { // Placement-new the Framebuffer since it has a constructor new (&ds->fb) Framebuffer(); + // Read username from spawn args + char username[32] = {}; + montauk::getargs(username, 32); + if (username[0] == '\0') { + montauk::strcpy(username, "default"); + } + montauk::strncpy(ds->current_user, username, 31); + + // Build user paths + montauk::user::home_dir(username, ds->home_dir, sizeof(ds->home_dir)); + montauk::user::config_dir(username, ds->user_config_dir, sizeof(ds->user_config_dir)); + + // Check if user is admin + ds->is_admin = false; + { + montauk::user::UserInfo users[16]; + int count = montauk::user::load_users(users, 16); + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { + ds->is_admin = montauk::streq(users[i].role, "admin"); + break; + } + } + } + g_desktop = ds; desktop_init(ds); diff --git a/programs/src/desktop/panel.cpp b/programs/src/desktop/panel.cpp index 434f751..e6ec131 100644 --- a/programs/src/desktop/panel.cpp +++ b/programs/src/desktop/panel.cpp @@ -105,14 +105,42 @@ void gui::desktop_draw_panel(DesktopState* ds) { int date_x = clock_x - date_w - 10; draw_text(fb, date_x, clock_y, date_str, colors::PANEL_TEXT); - // Network icon (to the left of the date) + // Volume icon (to the left of the date) uint64_t now = montauk::get_milliseconds(); + if (now - ds->vol_last_poll > 5000) { + int v = montauk::audio_get_volume(0); + if (v >= 0 && !ds->vol_muted) ds->vol_level = v; + ds->vol_last_poll = now; + } + + int vol_icon_x = date_x - 16 - 12; + int vol_icon_y = (PANEL_HEIGHT - 16) / 2; + ds->vol_icon_rect = {vol_icon_x, vol_icon_y, 16, 16}; + + if (ds->icon_volume.pixels) { + if (ds->vol_muted) { + // Tint red-ish when muted + uint32_t* src = ds->icon_volume.pixels; + int npx = 16 * 16; + uint32_t tinted[256]; + for (int p = 0; p < npx; p++) { + uint32_t px = src[p]; + uint8_t a = (px >> 24) & 0xFF; + tinted[p] = ((uint32_t)a << 24) | 0x00CC3333; + } + fb.blit_alpha(vol_icon_x, vol_icon_y, 16, 16, tinted); + } else { + fb.blit_alpha(vol_icon_x, vol_icon_y, ds->icon_volume.width, ds->icon_volume.height, ds->icon_volume.pixels); + } + } + + // Network icon (to the left of the volume icon) if (now - ds->net_cfg_last_poll > 5000) { montauk::get_netcfg(&ds->cached_net_cfg); ds->net_cfg_last_poll = now; } - int net_icon_x = date_x - 16 - 12; + int net_icon_x = vol_icon_x - 16 - 10; int net_icon_y = (PANEL_HEIGHT - 16) / 2; ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16}; @@ -237,51 +265,203 @@ void desktop_draw_app_menu(DesktopState* ds) { void desktop_draw_net_popup(DesktopState* ds) { Framebuffer& fb = ds->fb; + Montauk::NetCfg& nc = ds->cached_net_cfg; + bool connected = nc.ipAddress != 0; int popup_w = 220; - int popup_h = 130; + int fh = system_font_height(); + int row_h = fh + 8; + int header_h = row_h + 8; // title + status row + padding + int body_rows = 5; // IP, Subnet, Gateway, DNS, MAC + int popup_h = header_h + row_h * body_rows + 12; int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w; int popup_y = PANEL_HEIGHT + 2; if (popup_x < 4) popup_x = 4; draw_shadow(fb, popup_x, popup_y, popup_w, popup_h, 4, colors::SHADOW); - fb.fill_rect(popup_x, popup_y, popup_w, popup_h, colors::MENU_BG); + fill_rounded_rect(fb, popup_x, popup_y, popup_w, popup_h, 8, colors::MENU_BG); draw_rect(fb, popup_x, popup_y, popup_w, popup_h, colors::BORDER); - int tx = popup_x + 12; + int lx = popup_x + 14; int ty = popup_y + 10; - int line_h = system_font_height() + 6; - char line[64]; - Montauk::NetCfg& nc = ds->cached_net_cfg; + // Header: "Ethernet" + status dot + draw_text(fb, lx, ty, "Ethernet", colors::TEXT_COLOR); - if (nc.ipAddress != 0) { - char ipbuf[20]; - format_ip(ipbuf, nc.ipAddress); - snprintf(line, sizeof(line), "IP: %s", ipbuf); - } else { - snprintf(line, sizeof(line), "IP: Not connected"); + // Status dot + label (right-aligned in header) + Color dot_color = connected + ? Color::from_rgb(0x4C, 0xAF, 0x50) // green + : Color::from_rgb(0xCC, 0x33, 0x33); // red + const char* status_str = connected ? "Connected" : "Disconnected"; + int sw = text_width(status_str); + int dot_r = 4; + int status_x = popup_x + popup_w - 14 - sw; + int dot_x = status_x - dot_r * 2 - 5; + int dot_cy = ty + fh / 2; + for (int dy = -dot_r; dy <= dot_r; dy++) + for (int dx = -dot_r; dx <= dot_r; dx++) + if (dx * dx + dy * dy <= dot_r * dot_r) + fb.put_pixel(dot_x + dot_r + dx, dot_cy + dy, dot_color); + Color dim = Color::from_rgb(0x66, 0x66, 0x66); + draw_text(fb, status_x, ty, status_str, dim); + + ty += row_h + 2; + + // Separator line + for (int sx = popup_x + 10; sx < popup_x + popup_w - 10; sx++) + fb.put_pixel(sx, ty, colors::BORDER); + ty += 6; + + // Body rows: label (dim) + value (dark), two-column + int val_x = popup_x + 76; // fixed column for values + + struct NetRow { const char* label; char value[24]; }; + NetRow rows[5]; + + rows[0].label = "IP"; + if (connected) format_ip(rows[0].value, nc.ipAddress); + else montauk::strcpy(rows[0].value, "\xE2\x80\x94"); // em dash + + rows[1].label = "Subnet"; + format_ip(rows[1].value, nc.subnetMask); + + rows[2].label = "Gateway"; + format_ip(rows[2].value, nc.gateway); + + rows[3].label = "DNS"; + format_ip(rows[3].value, nc.dnsServer); + + rows[4].label = "MAC"; + format_mac(rows[4].value, nc.macAddress); + + for (int i = 0; i < body_rows; i++) { + draw_text(fb, lx, ty, rows[i].label, dim); + draw_text(fb, val_x, ty, rows[i].value, colors::TEXT_COLOR); + ty += row_h; } - draw_text(fb, tx, ty, line, colors::TEXT_COLOR); - ty += line_h; - - char buf[20]; - format_ip(buf, nc.subnetMask); - snprintf(line, sizeof(line), "Subnet: %s", buf); - draw_text(fb, tx, ty, line, colors::TEXT_COLOR); - ty += line_h; - - format_ip(buf, nc.gateway); - snprintf(line, sizeof(line), "Gateway: %s", buf); - draw_text(fb, tx, ty, line, colors::TEXT_COLOR); - ty += line_h; - - format_ip(buf, nc.dnsServer); - snprintf(line, sizeof(line), "DNS: %s", buf); - draw_text(fb, tx, ty, line, colors::TEXT_COLOR); - ty += line_h; - - format_mac(buf, nc.macAddress); - snprintf(line, sizeof(line), "MAC: %s", buf); - draw_text(fb, tx, ty, line, colors::TEXT_COLOR); +} + +// ============================================================================ +// Volume Popup +// ============================================================================ + +static constexpr int VOL_POPUP_W = 200; +static constexpr int VOL_POPUP_H = 120; +static constexpr int VOL_SLIDER_X = 16; +static constexpr int VOL_SLIDER_W = VOL_POPUP_W - 32; +static constexpr int VOL_SLIDER_H = 8; +static constexpr int VOL_KNOB_R = 8; + +void desktop_draw_vol_popup(DesktopState* ds) { + Framebuffer& fb = ds->fb; + + int popup_x = ds->vol_icon_rect.x + ds->vol_icon_rect.w - VOL_POPUP_W; + int popup_y = PANEL_HEIGHT + 2; + if (popup_x < 4) popup_x = 4; + + draw_shadow(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, 4, colors::SHADOW); + fill_rounded_rect(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, 8, colors::MENU_BG); + draw_rect(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, colors::BORDER); + + int display_vol = ds->vol_muted ? 0 : ds->vol_level; + + // Volume percentage label + char vol_str[8]; + snprintf(vol_str, sizeof(vol_str), "%d%%", display_vol); + int vw = text_width(vol_str); + Color vol_color = ds->vol_muted ? Color::from_rgb(0xCC, 0x33, 0x33) : ds->settings.accent_color; + draw_text(fb, popup_x + (VOL_POPUP_W - vw) / 2, popup_y + 12, vol_str, vol_color); + + // "Muted" sub-label + if (ds->vol_muted) { + const char* ml = "Muted"; + int mw = text_width(ml); + draw_text(fb, popup_x + (VOL_POPUP_W - mw) / 2, + popup_y + 12 + system_font_height() + 2, ml, + Color::from_rgb(0xCC, 0x33, 0x33)); + } + + // Slider track + int slider_abs_x = popup_x + VOL_SLIDER_X; + int slider_abs_y = popup_y + 56; + fill_rounded_rect(fb, slider_abs_x, slider_abs_y, VOL_SLIDER_W, VOL_SLIDER_H, 4, + Color::from_rgb(0xDD, 0xDD, 0xDD)); + + // Filled portion + int fill_w = (display_vol * VOL_SLIDER_W) / 100; + if (fill_w > 0) + fill_rounded_rect(fb, slider_abs_x, slider_abs_y, fill_w, VOL_SLIDER_H, 4, + ds->settings.accent_color); + + // Knob + int knob_cx = slider_abs_x + fill_w; + int knob_cy = slider_abs_y + VOL_SLIDER_H / 2; + // Draw filled circle for knob + for (int dy = -VOL_KNOB_R; dy <= VOL_KNOB_R; dy++) { + for (int dx = -VOL_KNOB_R; dx <= VOL_KNOB_R; dx++) { + if (dx * dx + dy * dy <= VOL_KNOB_R * VOL_KNOB_R) { + int px = knob_cx + dx; + int py = knob_cy + dy; + if (px >= 0 && px < ds->screen_w && py >= 0 && py < ds->screen_h) + fb.put_pixel(px, py, ds->settings.accent_color); + } + } + } + // White center + int inner_r = VOL_KNOB_R - 3; + for (int dy = -inner_r; dy <= inner_r; dy++) { + for (int dx = -inner_r; dx <= inner_r; dx++) { + if (dx * dx + dy * dy <= inner_r * inner_r) { + int px = knob_cx + dx; + int py = knob_cy + dy; + if (px >= 0 && px < ds->screen_w && py >= 0 && py < ds->screen_h) + fb.put_pixel(px, py, Color::from_rgb(0xFF, 0xFF, 0xFF)); + } + } + } + + // Buttons: [-] [+] [Mute] + int btn_h = 24; + int btn_y = popup_y + 78; + int btn_rad = 6; + + int minus_w = 36; + int plus_w = 36; + int mute_w = 50; + int gap = 8; + int total_w = minus_w + plus_w + mute_w + gap * 2; + int bx = popup_x + (VOL_POPUP_W - total_w) / 2; + + int mmx = ds->mouse.x; + int mmy = ds->mouse.y; + + // [-] button + Color minus_bg = Color::from_rgb(0xE0, 0xE0, 0xE0); + Rect minus_r = {bx, btn_y, minus_w, btn_h}; + if (minus_r.contains(mmx, mmy)) minus_bg = Color::from_rgb(0xD0, 0xD0, 0xD0); + fill_rounded_rect(fb, bx, btn_y, minus_w, btn_h, btn_rad, minus_bg); + int tw = text_width("-"); + draw_text(fb, bx + (minus_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "-", colors::TEXT_COLOR); + bx += minus_w + gap; + + // [+] button + Color plus_bg = Color::from_rgb(0xE0, 0xE0, 0xE0); + Rect plus_r = {bx, btn_y, plus_w, btn_h}; + if (plus_r.contains(mmx, mmy)) plus_bg = Color::from_rgb(0xD0, 0xD0, 0xD0); + fill_rounded_rect(fb, bx, btn_y, plus_w, btn_h, btn_rad, plus_bg); + tw = text_width("+"); + draw_text(fb, bx + (plus_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "+", colors::TEXT_COLOR); + bx += plus_w + gap; + + // [Mute] button + Color mute_bg = ds->vol_muted ? Color::from_rgb(0xCC, 0x33, 0x33) : Color::from_rgb(0xE0, 0xE0, 0xE0); + Color mute_fg = ds->vol_muted ? Color::from_rgb(0xFF, 0xFF, 0xFF) : colors::TEXT_COLOR; + Rect mute_r = {bx, btn_y, mute_w, btn_h}; + if (mute_r.contains(mmx, mmy)) { + if (ds->vol_muted) mute_bg = Color::from_rgb(0xAA, 0x22, 0x22); + else mute_bg = Color::from_rgb(0xD0, 0xD0, 0xD0); + } + fill_rounded_rect(fb, bx, btn_y, mute_w, btn_h, btn_rad, mute_bg); + tw = text_width("Mute"); + draw_text(fb, bx + (mute_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "Mute", mute_fg); } diff --git a/programs/src/httpd/main.cpp b/programs/src/httpd/main.cpp index 759a7e0..cd545b9 100644 --- a/programs/src/httpd/main.cpp +++ b/programs/src/httpd/main.cpp @@ -267,7 +267,26 @@ static int generate_index_page(char* buf, int bufSize) { (unsigned)hours, (unsigned)mins, (unsigned)secs); } +// HTML-escape a string to prevent XSS (escapes <, >, &, ", ') +static int html_escape(const char* in, char* out, int outMax) { + int j = 0; + for (int i = 0; in[i] && j < outMax - 6; i++) { + switch (in[i]) { + case '<': out[j++]='&'; out[j++]='l'; out[j++]='t'; out[j++]=';'; break; + case '>': out[j++]='&'; out[j++]='g'; out[j++]='t'; out[j++]=';'; break; + case '&': out[j++]='&'; out[j++]='a'; out[j++]='m'; out[j++]='p'; out[j++]=';'; break; + case '"': out[j++]='&'; out[j++]='q'; out[j++]='u'; out[j++]='o'; out[j++]='t'; out[j++]=';'; break; + case '\'': out[j++]='&'; out[j++]='#'; out[j++]='3'; out[j++]='9'; out[j++]=';'; break; + default: out[j++] = in[i]; break; + } + } + out[j] = '\0'; + return j; +} + static int generate_404_page(char* buf, int bufSize, const char* path) { + char escaped[512]; + html_escape(path, escaped, sizeof(escaped)); return snprintf(buf, bufSize, "\n" "\n" @@ -278,7 +297,7 @@ static int generate_404_page(char* buf, int bufSize, const char* path) { "

Back to home

\n" "\n" "\n", - path); + escaped); } static int generate_dir_listing(char* buf, int bufSize, const char* urlPath, const char* vfsDir) { @@ -322,10 +341,12 @@ static int generate_dir_listing(char* buf, int bufSize, const char* urlPath, con } if (*name == '\0') continue; - // Build the URL for this entry + // Build the URL for this entry (HTML-escape the name) + char esc_name[256]; + html_escape(name, esc_name, sizeof(esc_name)); pos += snprintf(buf + pos, bufSize - pos, "
  • %s
  • \n", - urlPath, name, name); + urlPath, name, esc_name); } pos += snprintf(buf + pos, bufSize - pos, @@ -415,6 +436,29 @@ static void handle_client(int clientFd) { // Serve file or directory from VFS const char* relPath = path + 7; // skip "/files/" + // Reject path traversal attempts + if (starts_with(relPath, "..") || starts_with(relPath, "/")) { + static char body[] = "

    403 Forbidden

    "; + send_response(clientFd, 403, "Forbidden", "text/html", body, slen(body)); + log_request("GET", path, 403, slen(body)); + montauk::closesocket(clientFd); + return; + } + // Check for /../ or trailing /.. anywhere in the path + for (int ci = 0; relPath[ci]; ci++) { + if (relPath[ci] == '.' && relPath[ci+1] == '.') { + if (ci == 0 || relPath[ci-1] == '/') { + if (relPath[ci+2] == '\0' || relPath[ci+2] == '/') { + static char body[] = "

    403 Forbidden

    "; + send_response(clientFd, 403, "Forbidden", "text/html", body, slen(body)); + log_request("GET", path, 403, slen(body)); + montauk::closesocket(clientFd); + return; + } + } + } + } + // Build VFS path: "0:/" char vfsPath[256]; int pi = 0; diff --git a/programs/src/init/main.cpp b/programs/src/init/main.cpp index f4e571d..be08797 100644 --- a/programs/src/init/main.cpp +++ b/programs/src/init/main.cpp @@ -157,10 +157,13 @@ extern "C" void _start() { // ---- Stage 1: Network configuration (non-blocking) ---- run_service("0:/os/dhcp.elf", "dhcp", false); - // ---- Stage 2: Desktop environment (falls back to shell) ---- - if (!run_service("0:/os/desktop.elf", "desktop")) { - log_warn("Desktop failed, falling back to shell"); - run_service("0:/os/shell.elf", "shell"); + // ---- Stage 2: Login screen -> desktop (falls back to desktop, then shell) ---- + if (!run_service("0:/os/login.elf", "login")) { + log_warn("Login failed, falling back to desktop"); + if (!run_service("0:/os/desktop.elf", "desktop")) { + log_warn("Desktop failed, falling back to shell"); + run_service("0:/os/shell.elf", "shell"); + } } log_warn("All services exited"); diff --git a/programs/src/login/Makefile b/programs/src/login/Makefile new file mode 100644 index 0000000..f56e4af --- /dev/null +++ b/programs/src/login/Makefile @@ -0,0 +1,94 @@ +# Makefile for login (graphical login screen) on MontaukOS +# Copyright (c) 2026 Daniel Hammer + +MAKEFLAGS += -rR +.SUFFIXES: + +# ---- Toolchain ---- + +TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf- +ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),) + CXX := $(TOOLCHAIN_PREFIX)g++ +else + CXX := g++ +endif + +# ---- Paths ---- + +PROG_INC := ../../include +LIBC_LIB := ../../lib/libc +JPEG_LIB := ../../lib/libjpeg +BEARSSL := ../../lib/bearssl +LINK_LD := ../../link.ld +BINDIR := ../../bin +OBJDIR := obj + +# ---- Compiler flags ---- + +CXXFLAGS := \ + -std=gnu++20 \ + -g -O2 -pipe \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -Wno-unused-function \ + -nostdinc \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -fno-PIC \ + -fno-rtti \ + -fno-exceptions \ + -ffunction-sections \ + -fdata-sections \ + -m64 \ + -march=x86-64 \ + -msse \ + -msse2 \ + -mno-red-zone \ + -mcmodel=small \ + -I $(PROG_INC) \ + -isystem $(PROG_INC)/libc \ + -I $(BEARSSL)/inc \ + -isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \ + -isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include + +# ---- Linker flags ---- + +LDFLAGS := \ + -nostdlib \ + -static \ + -Wl,--build-id=none \ + -Wl,--gc-sections \ + -Wl,-m,elf_x86_64 \ + -z max-page-size=0x1000 \ + -T $(LINK_LD) + +# ---- Source files ---- + +SRCS := main.cpp stb_truetype_impl.cpp font_data.cpp +OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o)) +DEPS := $(OBJS:.o=.d) + +# ---- Target ---- + +TARGET := $(BINDIR)/os/login.elf + +.PHONY: all clean + +all: $(TARGET) + +LIBS := $(JPEG_LIB)/libjpeg.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a + +$(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile + mkdir -p $(BINDIR)/os + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ + +$(OBJDIR)/%.o: %.cpp Makefile + mkdir -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@ + +-include $(DEPS) + +clean: + rm -rf $(OBJDIR) $(TARGET) diff --git a/programs/src/login/font_data.cpp b/programs/src/login/font_data.cpp new file mode 100644 index 0000000..940f6e1 --- /dev/null +++ b/programs/src/login/font_data.cpp @@ -0,0 +1,783 @@ +/* + * font_data.cpp + * Standard VGA 8x16 bitmap font (Code Page 437) + * 256 characters, 16 bytes each (8 pixels wide, 1 bit per pixel, MSB left) + * Copyright (c) 2025 Daniel Hammer +*/ + +#include "gui/font.hpp" + +namespace gui { + +const uint8_t font_data[256 * 16] = { + // Character 0 (NUL) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 1 (smiley face) + 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, + 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 2 (inverse smiley) + 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, + 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 3 (heart) + 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, + 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + // Character 4 (diamond) + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, + 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 5 (club) + 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, + 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 6 (spade) + 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, + 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 7 (bullet) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, + 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 8 (inverse bullet) + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, + 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // Character 9 (circle) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, + 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 10 (inverse circle) + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, + 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // Character 11 (male sign) + 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, + 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, + // Character 12 (female sign) + 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, + 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 13 (note) + 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, + 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, + // Character 14 (double note) + 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, + 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, + // Character 15 (sun) + 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, + 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 16 (right triangle) + 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, + 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, + // Character 17 (left triangle) + 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, + 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + // Character 18 (up-down arrow) + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, + 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 19 (double exclamation) + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + // Character 20 (paragraph) + 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, + 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, + // Character 21 (section) + 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, + 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, + // Character 22 (thick underscore) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 23 (up-down arrow underlined) + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, + 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 24 (up arrow) + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 25 (down arrow) + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 26 (right arrow) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, + 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 27 (left arrow) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, + 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 28 (right angle) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, + 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 29 (left-right arrow) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, + 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 30 (up triangle) + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, + 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 31 (down triangle) + 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, + 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 32 (space) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 33 '!' + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 34 '"' + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 35 '#' + 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, + 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + // Character 36 '$' + 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, + 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, + // Character 37 '%' + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, + 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, + // Character 38 '&' + 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 39 ''' + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 40 '(' + 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, + // Character 41 ')' + 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + // Character 42 '*' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, + 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 43 '+' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 44 ',' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + // Character 45 '-' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 46 '.' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 47 '/' + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, + // Character 48 '0' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, + 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 49 '1' + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 50 '2' + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 51 '3' + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, + 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 52 '4' + 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, + 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, + // Character 53 '5' + 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06, + 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 54 '6' + 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 55 '7' + 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, + 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + // Character 56 '8' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 57 '9' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, + 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, + // Character 58 ':' + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 59 ';' + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + // Character 60 '<' + 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, + // Character 61 '=' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 62 '>' + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + // Character 63 '?' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 64 '@' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xDE, + 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 65 'A' + 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 66 'B' + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, + 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, + // Character 67 'C' + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 68 'D' + 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, + // Character 69 'E' + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 70 'F' + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + // Character 71 'G' + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, + 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, + // Character 72 'H' + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 73 'I' + 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 74 'J' + 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, + // Character 75 'K' + 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, + 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + // Character 76 'L' + 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 77 'M' + 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 78 'N' + 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 79 'O' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 80 'P' + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + // Character 81 'Q' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, + // Character 82 'R' + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, + 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + // Character 83 'S' + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, + 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 84 'T' + 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 85 'U' + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 86 'V' + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + // Character 87 'W' + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, + 0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, + // Character 88 'X' + 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, + 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 89 'Y' + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 90 'Z' + 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, + 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 91 '[' + 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 92 '\' + 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, + 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + // Character 93 ']' + 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 94 '^' + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 95 '_' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + // Character 96 '`' + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 97 'a' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 98 'b' + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, + 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 99 'c' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 100 'd' + 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 101 'e' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 102 'f' + 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + // Character 103 'g' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, + // Character 104 'h' + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, + 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + // Character 105 'i' + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 106 'j' + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, + // Character 107 'k' + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, + 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + // Character 108 'l' + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 109 'm' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, + 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 110 'n' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + // Character 111 'o' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 112 'p' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + // Character 113 'q' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, + // Character 114 'r' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + // Character 115 's' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, + 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 116 't' + 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, + 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, + // Character 117 'u' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 118 'v' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + // Character 119 'w' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, + 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, + // Character 120 'x' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, + 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 121 'y' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, + // Character 122 'z' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, + 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 123 '{' + 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, + 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, + // Character 124 '|' + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 125 '}' + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, + 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + // Character 126 '~' + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 127 (DEL - block) + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, + 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 128 (C cedilla) + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, + 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00, + // Character 129 (u umlaut) + 0x00, 0x00, 0xCC, 0x00, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 130 (e acute) + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 131 (a circumflex) + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 132 (a umlaut) + 0x00, 0x00, 0xCC, 0x00, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 133 (a grave) + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 134 (a ring) + 0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 135 (c cedilla) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, + 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, 0x00, 0x00, + // Character 136 (e circumflex) + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 137 (e umlaut) + 0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 138 (e grave) + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 139 (i umlaut) + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 140 (i circumflex) + 0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 141 (i grave) + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 142 (A umlaut) + 0x00, 0xC6, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, + 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 143 (A ring) + 0x38, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0xC6, 0xC6, + 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 144 (E acute) + 0x0C, 0x18, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, + 0x68, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 145 (ae) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x3B, 0x1B, + 0x7E, 0xD8, 0xDC, 0x77, 0x00, 0x00, 0x00, 0x00, + // Character 146 (AE) + 0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00, + // Character 147 (o circumflex) + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 148 (o umlaut) + 0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 149 (o grave) + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 150 (u circumflex) + 0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 151 (u grave) + 0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 152 (y umlaut) + 0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00, + // Character 153 (O umlaut) + 0x00, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 154 (U umlaut) + 0x00, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 155 (cent) + 0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, + 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 156 (pound) + 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, + 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00, + // Character 157 (yen) + 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0xFE, 0x38, + 0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, + // Character 158 (Pt) + 0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, + 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 159 (f hook) + 0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, + 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, + // Character 160 (a acute) + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 161 (i acute) + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 162 (o acute) + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 163 (u acute) + 0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 164 (n tilde) + 0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + // Character 165 (N tilde) + 0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, + 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 166 (feminine ordinal) + 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 167 (masculine ordinal) + 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 168 (inverted question) + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, + 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + // Character 169 (not left) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, + 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 170 (not right) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, + 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 171 (fraction 1/2) + 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, + 0x60, 0xDC, 0x86, 0x0C, 0x18, 0x3E, 0x00, 0x00, + // Character 172 (fraction 1/4) + 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, + 0x66, 0xCE, 0x9E, 0x3E, 0x06, 0x06, 0x00, 0x00, + // Character 173 (inverted exclamation) + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, + 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 174 (double left angle) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6C, 0xD8, + 0x6C, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 175 (double right angle) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x6C, 0x36, + 0x6C, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 176 (light shade) + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + // Character 177 (medium shade) + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + // Character 178 (dark shade) + 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, + 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, + // Character 179 (box vertical) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 180 (box vertical-left) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 181 (box double vertical-left single) + 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 182 (box double vertical-left) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 183 (box double horizontal-down) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 184 (box double vertical-left single) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 185 (box double vertical-left double) + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 186 (box double vertical) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 187 (box double down-left) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 188 (box double up-left) + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 189 (box double up-right) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 190 (box horizontal-down) + 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 191 (box down-left) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 192 (box up-right) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 193 (box horizontal-up) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 194 (box horizontal-down) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 195 (box vertical-right) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 196 (box horizontal) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 197 (box cross) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 198 (box single vert-right double) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 199 (box double vert-right) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 200 (box double up-right) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 201 (box double down-right) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 202 (box double horizontal-up) + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 203 (box double horizontal-down) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 204 (box double vertical-right) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 205 (box double horizontal) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 206 (box double cross) + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 207 (box single horiz-up double) + 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 208 (box double horizontal-up single) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 209 (box single horiz-down double) + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 210 (box double horizontal-down single) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 211 (box double up-right single) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 212 (box single up-right double) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 213 (box single down-right double) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 214 (box double down-right single) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 215 (box double cross single) + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + // Character 216 (box single cross double) + 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 217 (box up-left) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 218 (box down-right) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 219 (full block) + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // Character 220 (bottom half block) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // Character 221 (left half block) + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + // Character 222 (right half block) + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + // Character 223 (top half block) + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 224 (alpha) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, + 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00, + // Character 225 (beta/sharp s) + 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0xD8, 0xCC, + 0xC6, 0xC6, 0xC6, 0xCC, 0x00, 0x00, 0x00, 0x00, + // Character 226 (gamma) + 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, + // Character 227 (pi) + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, + 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + // Character 228 (sigma uppercase) + 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, + 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + // Character 229 (sigma lowercase) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, + 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, + // Character 230 (mu) + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, + // Character 231 (tau) + 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + // Character 232 (phi uppercase) + 0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, + 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 233 (theta) + 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, + 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + // Character 234 (omega) + 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, + 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00, + // Character 235 (delta) + 0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, + 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, + // Character 236 (infinity) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDB, 0xDB, + 0xDB, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 237 (phi lowercase) + 0x00, 0x00, 0x00, 0x02, 0x06, 0x7C, 0xCE, 0xDE, + 0xF6, 0xE6, 0x7C, 0xC0, 0x80, 0x00, 0x00, 0x00, + // Character 238 (epsilon) + 0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, + 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00, + // Character 239 (intersection) + 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + // Character 240 (triple bar) + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, + 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 241 (plus-minus) + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, + 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + // Character 242 (greater-equal) + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, + 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 243 (less-equal) + 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, + 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + // Character 244 (top integral) + 0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + // Character 245 (bottom integral) + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, + // Character 246 (division) + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 247 (approximately equal) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, + 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 248 (degree) + 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 249 (bullet operator) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 250 (middle dot) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 251 (square root) + 0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, + 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00, + // Character 252 (superscript n) + 0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 253 (superscript 2) + 0x00, 0x70, 0xD8, 0x30, 0x60, 0xC8, 0xF8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 254 (filled square) + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, + 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, + // Character 255 (non-breaking space) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +} // namespace gui diff --git a/programs/src/login/main.cpp b/programs/src/login/main.cpp new file mode 100644 index 0000000..627cb2d --- /dev/null +++ b/programs/src/login/main.cpp @@ -0,0 +1,790 @@ +/* + * main.cpp + * MontaukOS graphical login screen + * Copyright (c) 2026 Daniel Hammer +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Forward-declare stb_image functions (implementation in libjpeg.a). +extern "C" { + unsigned char* stbi_load_from_memory(const unsigned char* buffer, int len, + int* x, int* y, int* channels_in_file, + int desired_channels); + void stbi_image_free(void* retval_from_stbi_load); +} + +using namespace gui; + +// Placement new +inline void* operator new(unsigned long, void* p) { return p; } + +// ---- Minimal snprintf ---- + +using va_list = __builtin_va_list; +#define va_start __builtin_va_start +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg + +struct PfState { char* buf; int pos; int max; }; +static void pf_putc(PfState* st, char c) { + if (st->pos < st->max) st->buf[st->pos] = c; + st->pos++; +} +static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) { + char tmp[24]; int i = 0; + const char* digits = "0123456789abcdef"; + if (val == 0) { tmp[i++] = '0'; } + else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } } + int total = (neg ? 1 : 0) + i; + if (neg && pad == '0') pf_putc(st, '-'); + for (int w = total; w < width; w++) pf_putc(st, pad); + if (neg && pad != '0') pf_putc(st, '-'); + while (i > 0) pf_putc(st, tmp[--i]); +} +static int snprintf(char* buf, int size, const char* fmt, ...) { + va_list ap; va_start(ap, fmt); + PfState st; st.buf = buf; st.pos = 0; st.max = size > 0 ? size - 1 : 0; + while (*fmt) { + if (*fmt != '%') { pf_putc(&st, *fmt++); continue; } + fmt++; + char pad = ' '; + if (*fmt == '0') { pad = '0'; fmt++; } + int width = 0; + while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; } + if (*fmt == 'l') fmt++; + switch (*fmt) { + case 'd': case 'i': { + long val = va_arg(ap, int); + int neg = 0; unsigned long uval; + if (val < 0) { neg = 1; uval = (unsigned long)(-val); } else uval = (unsigned long)val; + pf_putnum(&st, uval, 10, width, pad, neg); break; + } + case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; } + case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; } + case 's': { + const char* s = va_arg(ap, const char*); if (!s) s = "(null)"; + int slen = 0; while (s[slen]) slen++; + for (int w = slen; w < width; w++) pf_putc(&st, ' '); + for (int j = 0; j < slen; j++) pf_putc(&st, s[j]); + break; + } + case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; } + case '%': pf_putc(&st, '%'); break; + default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break; + } + if (*fmt) fmt++; + } + if (size > 0) { if (st.pos < size) st.buf[st.pos] = '\0'; else st.buf[size - 1] = '\0'; } + va_end(ap); return st.pos; +} + +// ============================================================================ +// Login state +// ============================================================================ + +enum LoginMode { + MODE_FIRST_BOOT, // Create admin account + MODE_LOGIN, // Normal login +}; + +struct LoginState { + Framebuffer fb; + int screen_w, screen_h; + + LoginMode mode; + int active_field; // 0=username, 1=password, 2=confirm (first-boot only) + + char username[32]; + int username_len; + char display_name[64]; + int display_name_len; + char password[64]; + int password_len; + char confirm[64]; + int confirm_len; + + char error_msg[128]; + bool show_error; + + Montauk::MouseState mouse; + uint8_t prev_buttons; + + // Power option icons (loaded once at startup) + SvgIcon icon_shutdown; + SvgIcon icon_reboot; + + // Background wallpaper (loaded from config) + uint32_t* bg_wallpaper; + int bg_wallpaper_w, bg_wallpaper_h; + bool has_wallpaper; +}; + +// ============================================================================ +// Wallpaper loading +// ============================================================================ + +static bool load_login_wallpaper(LoginState* ls) { + // Load system-wide desktop config and read wallpaper.path + auto doc = montauk::config::load("desktop"); + const char* wp = doc.get_string("wallpaper.path", ""); + if (wp[0] == '\0') return false; + + // Read JPEG file + int fd = montauk::open(wp); + if (fd < 0) return false; + + uint64_t size = montauk::getsize(fd); + if (size == 0 || size > 16 * 1024 * 1024) { + montauk::close(fd); + return false; + } + + uint8_t* filedata = (uint8_t*)montauk::malloc(size); + if (!filedata) { montauk::close(fd); return false; } + + int bytes_read = montauk::read(fd, filedata, 0, size); + montauk::close(fd); + if (bytes_read <= 0) { montauk::mfree(filedata); return false; } + + // Decode JPEG + int img_w, img_h, channels; + unsigned char* rgb = stbi_load_from_memory(filedata, bytes_read, + &img_w, &img_h, &channels, 3); + montauk::mfree(filedata); + if (!rgb) return false; + + // Scale to cover screen (same algorithm as desktop wallpaper.hpp) + int dst_w = ls->screen_w; + int dst_h = ls->screen_h; + + uint32_t* scaled = (uint32_t*)montauk::malloc((uint64_t)dst_w * dst_h * 4); + if (!scaled) { stbi_image_free(rgb); return false; } + + int src_crop_w, src_crop_h, src_x0, src_y0; + if ((int64_t)img_w * dst_h > (int64_t)img_h * dst_w) { + src_crop_h = img_h; + src_crop_w = (int)((int64_t)img_h * dst_w / dst_h); + src_x0 = (img_w - src_crop_w) / 2; + src_y0 = 0; + } else { + src_crop_w = img_w; + src_crop_h = (int)((int64_t)img_w * dst_h / dst_w); + src_x0 = 0; + src_y0 = (img_h - src_crop_h) / 2; + } + + for (int y = 0; y < dst_h; y++) { + int sy = src_y0 + (int)((int64_t)y * src_crop_h / dst_h); + if (sy < 0) sy = 0; + if (sy >= img_h) sy = img_h - 1; + for (int x = 0; x < dst_w; x++) { + int sx = src_x0 + (int)((int64_t)x * src_crop_w / dst_w); + if (sx < 0) sx = 0; + if (sx >= img_w) sx = img_w - 1; + int si = (sy * img_w + sx) * 3; + scaled[y * dst_w + x] = 0xFF000000u + | ((uint32_t)rgb[si] << 16) + | ((uint32_t)rgb[si + 1] << 8) + | (uint32_t)rgb[si + 2]; + } + } + + stbi_image_free(rgb); + + ls->bg_wallpaper = scaled; + ls->bg_wallpaper_w = dst_w; + ls->bg_wallpaper_h = dst_h; + ls->has_wallpaper = true; + return true; +} + +// ============================================================================ +// Drawing helpers +// ============================================================================ + +static constexpr Color BG_COLOR = Color::from_rgb(0x2B, 0x3E, 0x50); +static constexpr Color CARD_BG = Color::from_rgb(0xFF, 0xFF, 0xFF); +static constexpr Color FIELD_BG = Color::from_rgb(0xF5, 0xF5, 0xF5); +static constexpr Color FIELD_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC); +static constexpr Color FIELD_ACTIVE = Color::from_rgb(0x36, 0x7B, 0xF0); +static constexpr Color BTN_COLOR = Color::from_rgb(0x36, 0x7B, 0xF0); +static constexpr Color BTN_TEXT = Color::from_rgb(0xFF, 0xFF, 0xFF); +static constexpr Color TEXT_COLOR = Color::from_rgb(0x33, 0x33, 0x33); +static constexpr Color LABEL_COLOR = Color::from_rgb(0x66, 0x66, 0x66); +static constexpr Color ERROR_COLOR = Color::from_rgb(0xE0, 0x40, 0x40); +static constexpr Color TITLE_COLOR = Color::from_rgb(0xFF, 0xFF, 0xFF); + +static constexpr int CARD_W = 360; +static constexpr int FIELD_H = 36; +static constexpr int FIELD_PAD = 10; +static constexpr int BTN_H = 40; +static constexpr int LABEL_GAP = 4; +static constexpr int POWER_ICON_SZ = 32; +static constexpr int POWER_GAP = 48; // horizontal spacing between icon centers +static constexpr int POWER_TOP_PAD = 24; // padding below error message area + +static void draw_field(Framebuffer& fb, int x, int y, int w, const char* text, + bool is_password, bool active) { + // Background + fb.fill_rect(x, y, w, FIELD_H, FIELD_BG); + + // Border + Color border = active ? FIELD_ACTIVE : FIELD_BORDER; + // Top + for (int i = 0; i < w; i++) fb.put_pixel(x + i, y, border); + // Bottom + for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + FIELD_H - 1, border); + // Left + for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x, y + i, border); + // Right + for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + w - 1, y + i, border); + + if (active) { + // Draw 2px border for active field + for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + 1, border); + for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + FIELD_H - 2, border); + for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + 1, y + i, border); + for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + w - 2, y + i, border); + } + + // Text (clipped to field width, showing trailing portion) + int ty = y + (FIELD_H - system_font_height()) / 2; + int max_text_w = w - FIELD_PAD * 2 - 2; // left pad, right pad, cursor + if (is_password) { + int len = montauk::slen(text); + if (len > 64) len = 64; + char full[65]; + for (int i = 0; i < len; i++) full[i] = '*'; + full[len] = '\0'; + // Show only trailing portion that fits + int vis = len; + while (vis > 0 && text_width(full + (len - vis)) > max_text_w) + vis--; + char masked[65]; + for (int i = 0; i < vis; i++) masked[i] = '*'; + masked[vis] = '\0'; + draw_text(fb, x + FIELD_PAD, ty, masked, TEXT_COLOR); + if (active) { + int cx = x + FIELD_PAD + text_width(masked); + fb.fill_rect(cx, ty, 2, system_font_height(), FIELD_ACTIVE); + } + } else { + int len = montauk::slen(text); + // Show only trailing portion that fits + int offset = 0; + while (text_width(text + offset) > max_text_w && offset < len) + offset++; + draw_text(fb, x + FIELD_PAD, ty, text + offset, TEXT_COLOR); + if (active) { + int cx = x + FIELD_PAD + text_width(text + offset); + fb.fill_rect(cx, ty, 2, system_font_height(), FIELD_ACTIVE); + } + } +} + +static void draw_button(Framebuffer& fb, int x, int y, int w, int h, + const char* label, Color bg) { + fb.fill_rect(x, y, w, h, bg); + int tw = text_width(label); + int tx = x + (w - tw) / 2; + int ty = y + (h - system_font_height()) / 2; + draw_text(fb, tx, ty, label, BTN_TEXT); +} + +// ============================================================================ +// Screen drawing +// ============================================================================ + +static void draw_login_screen(LoginState* ls) { + Framebuffer& fb = ls->fb; + + // Background + if (ls->has_wallpaper) { + fb.blit(0, 0, ls->bg_wallpaper_w, ls->bg_wallpaper_h, ls->bg_wallpaper); + } else { + fb.clear(BG_COLOR); + } + + int card_h; + const char* title; + int sfh = system_font_height(); + int power_section_h = POWER_ICON_SZ + sfh + 6 + 4; // icon + label + gap + padding + int error_section_h = ls->show_error ? sfh + 8 : 0; // error text + padding + if (ls->mode == MODE_FIRST_BOOT) { + card_h = 420 + error_section_h + power_section_h; + title = "Create Administrator Account"; + } else { + card_h = 284 + error_section_h + power_section_h; + title = "Log In"; + } + + int card_x = (ls->screen_w - CARD_W) / 2; + int card_y = (ls->screen_h - card_h) / 2; + + // Card background + fb.fill_rect(card_x, card_y, CARD_W, card_h, CARD_BG); + + int x = card_x + 24; + int content_w = CARD_W - 48; + int y = card_y + 20; + + // Card title + { + int tw = text_width(title); + draw_text(fb, card_x + (CARD_W - tw) / 2, y, title, TEXT_COLOR); + y += sfh + 16; + } + + if (ls->mode == MODE_FIRST_BOOT) { + // Username field + draw_text(fb, x, y, "Username", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->username, false, ls->active_field == 0); + y += FIELD_H + 12; + + // Display name field + draw_text(fb, x, y, "Display Name", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->display_name, false, ls->active_field == 1); + y += FIELD_H + 12; + + // Password field + draw_text(fb, x, y, "Password", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->password, true, ls->active_field == 2); + y += FIELD_H + 12; + + // Confirm password field + draw_text(fb, x, y, "Confirm Password", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->confirm, true, ls->active_field == 3); + y += FIELD_H + 16; + + // Create button + draw_button(fb, x, y, content_w, BTN_H, "Create Account", BTN_COLOR); + y += BTN_H; + } else { + // Username field + draw_text(fb, x, y, "Username", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->username, false, ls->active_field == 0); + y += FIELD_H + 12; + + // Password field + draw_text(fb, x, y, "Password", LABEL_COLOR); + y += sfh + LABEL_GAP; + draw_field(fb, x, y, content_w, ls->password, true, ls->active_field == 1); + y += FIELD_H + 16; + + // Login button + draw_button(fb, x, y, content_w, BTN_H, "Log In", BTN_COLOR); + y += BTN_H; + } + + // Error message (inside card, between button and separator) + if (ls->show_error) { + y += 8; + int tw = text_width(ls->error_msg); + draw_text(fb, card_x + (CARD_W - tw) / 2, y, ls->error_msg, ERROR_COLOR); + y += sfh; + } + + // Separator line + y += 16; + fb.fill_rect(x, y, content_w, 1, FIELD_BORDER); + y += 16; + + // Power options (inside card, centered) + { + int total_w = POWER_ICON_SZ + POWER_GAP + POWER_ICON_SZ; + int start_x = card_x + (CARD_W - total_w) / 2; + + // Shutdown icon + if (ls->icon_shutdown.pixels) { + int ix = start_x; + fb.blit_alpha(ix, y, ls->icon_shutdown.width, ls->icon_shutdown.height, + ls->icon_shutdown.pixels); + const char* lbl = "Shut Down"; + int lw = text_width(lbl); + draw_text(fb, ix + (POWER_ICON_SZ - lw) / 2, y + POWER_ICON_SZ + 6, + lbl, LABEL_COLOR); + } + + // Reboot icon + if (ls->icon_reboot.pixels) { + int ix = start_x + POWER_ICON_SZ + POWER_GAP; + fb.blit_alpha(ix, y, ls->icon_reboot.width, ls->icon_reboot.height, + ls->icon_reboot.pixels); + const char* lbl = "Restart"; + int lw = text_width(lbl); + draw_text(fb, ix + (POWER_ICON_SZ - lw) / 2, y + POWER_ICON_SZ + 6, + lbl, LABEL_COLOR); + } + } + + // Mouse cursor (shared with desktop) + draw_cursor(fb, ls->mouse.x, ls->mouse.y); + + fb.flip(); +} + +// ============================================================================ +// Input handling +// ============================================================================ + +static void append_char(char* buf, int* len, int max, char c) { + if (*len < max - 1) { + buf[*len] = c; + (*len)++; + buf[*len] = '\0'; + } +} + +static void backspace(char* buf, int* len) { + if (*len > 0) { + (*len)--; + buf[*len] = '\0'; + } +} + +static int max_fields(LoginState* ls) { + return ls->mode == MODE_FIRST_BOOT ? 4 : 2; +} + +static bool try_first_boot_submit(LoginState* ls) { + ls->show_error = false; + + if (ls->username_len == 0) { + montauk::strcpy(ls->error_msg, "Username is required"); + ls->show_error = true; + return false; + } + if (ls->password_len == 0) { + montauk::strcpy(ls->error_msg, "Password is required"); + ls->show_error = true; + return false; + } + if (!montauk::streq(ls->password, ls->confirm)) { + montauk::strcpy(ls->error_msg, "Passwords do not match"); + ls->show_error = true; + return false; + } + + // Create the users directory + montauk::fmkdir("0:/users"); + + const char* dname = ls->display_name_len > 0 ? ls->display_name : ls->username; + if (!montauk::user::create_user(ls->username, dname, ls->password, "admin")) { + montauk::strcpy(ls->error_msg, "Failed to create user"); + ls->show_error = true; + return false; + } + + return true; +} + +static bool try_login(LoginState* ls) { + ls->show_error = false; + + if (ls->username_len == 0) { + montauk::strcpy(ls->error_msg, "Username is required"); + ls->show_error = true; + return false; + } + + if (!montauk::user::authenticate(ls->username, ls->password)) { + montauk::strcpy(ls->error_msg, "Invalid username or password"); + ls->show_error = true; + return false; + } + + // Write session so any app can query the current user + montauk::user::set_session(ls->username); + return true; +} + +static void handle_key(LoginState* ls, const Montauk::KeyEvent& key) { + if (!key.pressed) return; + + // Tab switches fields + if (key.scancode == 0x0F) { + int mf = max_fields(ls); + if (key.shift) { + ls->active_field = (ls->active_field + mf - 1) % mf; + } else { + ls->active_field = (ls->active_field + 1) % mf; + } + ls->show_error = false; + return; + } + + // Enter submits + if (key.ascii == '\n' || key.ascii == '\r') { + if (ls->mode == MODE_FIRST_BOOT) { + if (try_first_boot_submit(ls)) { + // Switch to login mode + ls->mode = MODE_LOGIN; + ls->active_field = 0; + // Keep username, clear password fields + ls->password[0] = '\0'; ls->password_len = 0; + ls->confirm[0] = '\0'; ls->confirm_len = 0; + ls->show_error = false; + } + } else { + if (try_login(ls)) { + // Spawn desktop with username + int pid = montauk::spawn("0:/os/desktop.elf", ls->username); + if (pid >= 0) { + montauk::waitpid(pid); + } + // Desktop exited (logout) — clear session and fields + montauk::user::clear_session(); + ls->password[0] = '\0'; ls->password_len = 0; + ls->active_field = 1; // Focus password field + ls->show_error = false; + } + } + return; + } + + // Backspace + if (key.ascii == '\b' || key.scancode == 0x0E) { + if (ls->mode == MODE_FIRST_BOOT) { + switch (ls->active_field) { + case 0: backspace(ls->username, &ls->username_len); break; + case 1: backspace(ls->display_name, &ls->display_name_len); break; + case 2: backspace(ls->password, &ls->password_len); break; + case 3: backspace(ls->confirm, &ls->confirm_len); break; + } + } else { + switch (ls->active_field) { + case 0: backspace(ls->username, &ls->username_len); break; + case 1: backspace(ls->password, &ls->password_len); break; + } + } + return; + } + + // Printable characters + if (key.ascii >= 0x20 && key.ascii < 0x7F) { + if (ls->mode == MODE_FIRST_BOOT) { + switch (ls->active_field) { + case 0: append_char(ls->username, &ls->username_len, 31, key.ascii); break; + case 1: append_char(ls->display_name, &ls->display_name_len, 63, key.ascii); break; + case 2: append_char(ls->password, &ls->password_len, 63, key.ascii); break; + case 3: append_char(ls->confirm, &ls->confirm_len, 63, key.ascii); break; + } + } else { + switch (ls->active_field) { + case 0: append_char(ls->username, &ls->username_len, 31, key.ascii); break; + case 1: append_char(ls->password, &ls->password_len, 63, key.ascii); break; + } + } + } +} + +static void handle_mouse(LoginState* ls) { + int mx = ls->mouse.x; + int my = ls->mouse.y; + uint8_t buttons = ls->mouse.buttons; + uint8_t prev = ls->prev_buttons; + bool left_pressed = (buttons & 0x01) && !(prev & 0x01); + + if (!left_pressed) return; + + int sfh = system_font_height(); + int power_section_h = POWER_ICON_SZ + sfh + 6 + 8; + int error_section_h = ls->show_error ? sfh + 8 : 0; + int card_h; + if (ls->mode == MODE_FIRST_BOOT) { + card_h = 420 + error_section_h + power_section_h; + } else { + card_h = 284 + error_section_h + power_section_h; + } + int card_x = (ls->screen_w - CARD_W) / 2; + int card_y = (ls->screen_h - card_h) / 2; + int x = card_x + 24; + int content_w = CARD_W - 48; + int y = card_y + 20; + + // Skip title + y += sfh + 16; + + if (ls->mode == MODE_FIRST_BOOT) { + // Username label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 0; + return; + } + y += FIELD_H + 12; + + // Display name label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 1; + return; + } + y += FIELD_H + 12; + + // Password label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 2; + return; + } + y += FIELD_H + 12; + + // Confirm label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 3; + return; + } + y += FIELD_H + 16; + + // Create button + if (mx >= x && mx < x + content_w && my >= y && my < y + BTN_H) { + if (try_first_boot_submit(ls)) { + ls->mode = MODE_LOGIN; + ls->active_field = 0; + ls->password[0] = '\0'; ls->password_len = 0; + ls->confirm[0] = '\0'; ls->confirm_len = 0; + ls->show_error = false; + } + return; + } + y += BTN_H; + } else { + // Username label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 0; + return; + } + y += FIELD_H + 12; + + // Password label + field + y += sfh + LABEL_GAP; + if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) { + ls->active_field = 1; + return; + } + y += FIELD_H + 16; + + // Login button + if (mx >= x && mx < x + content_w && my >= y && my < y + BTN_H) { + if (try_login(ls)) { + int pid = montauk::spawn("0:/os/desktop.elf", ls->username); + if (pid >= 0) { + montauk::waitpid(pid); + } + montauk::user::clear_session(); + ls->password[0] = '\0'; ls->password_len = 0; + ls->active_field = 1; + ls->show_error = false; + } + return; + } + y += BTN_H; + } + + // Skip error section if visible + if (ls->show_error) y += error_section_h; + + // Power options (inside card, after separator) + y += 16 + 1 + 16; // padding + separator + padding + { + int total_w = POWER_ICON_SZ + POWER_GAP + POWER_ICON_SZ; + int start_x = card_x + (CARD_W - total_w) / 2; + int hit_h = POWER_ICON_SZ + sfh + 6; + + // Shutdown + if (mx >= start_x && mx < start_x + POWER_ICON_SZ && + my >= y && my < y + hit_h) { + montauk::shutdown(); + } + + // Reboot + int rx = start_x + POWER_ICON_SZ + POWER_GAP; + if (mx >= rx && mx < rx + POWER_ICON_SZ && + my >= y && my < y + hit_h) { + montauk::reset(); + } + } +} + +// ============================================================================ +// Entry point +// ============================================================================ + +extern "C" void _start() { + LoginState* ls = (LoginState*)montauk::malloc(sizeof(LoginState)); + montauk::memset(ls, 0, sizeof(LoginState)); + + new (&ls->fb) Framebuffer(); + ls->screen_w = ls->fb.width(); + ls->screen_h = ls->fb.height(); + + // Load TrueType fonts + fonts::init(); + + // Set mouse bounds + montauk::set_mouse_bounds(ls->screen_w - 1, ls->screen_h - 1); + + // Load power option icons + Color icon_color = Color::from_rgb(0x66, 0x66, 0x66); + ls->icon_shutdown = svg_load("0:/icons/system-shutdown.svg", POWER_ICON_SZ, POWER_ICON_SZ, icon_color); + ls->icon_reboot = svg_load("0:/icons/system-reboot.svg", POWER_ICON_SZ, POWER_ICON_SZ, icon_color); + + // Load wallpaper from system desktop config + load_login_wallpaper(ls); + + // Check if users.toml exists (first boot detection) + int fh = montauk::open("0:/config/users.toml"); + if (fh < 0) { + ls->mode = MODE_FIRST_BOOT; + ls->active_field = 0; + // Pre-fill username with "admin" + montauk::strcpy(ls->username, "admin"); + ls->username_len = 5; + } else { + montauk::close(fh); + ls->mode = MODE_LOGIN; + ls->active_field = 0; + } + + // Main loop + for (;;) { + // Poll mouse + ls->prev_buttons = ls->mouse.buttons; + montauk::mouse_state(&ls->mouse); + + // Poll keyboard + while (montauk::is_key_available()) { + Montauk::KeyEvent key; + montauk::getkey(&key); + handle_key(ls, key); + } + + // Handle mouse + handle_mouse(ls); + + // Draw + draw_login_screen(ls); + + // ~30fps (login doesn't need 60) + montauk::sleep_ms(33); + } +} diff --git a/programs/src/login/stb_truetype_impl.cpp b/programs/src/login/stb_truetype_impl.cpp new file mode 100644 index 0000000..9ce2266 --- /dev/null +++ b/programs/src/login/stb_truetype_impl.cpp @@ -0,0 +1,35 @@ +/* + * stb_truetype_impl.cpp + * Single compilation unit for stb_truetype in MontaukOS freestanding environment + * Copyright (c) 2026 Daniel Hammer + */ + +#include +#include +#include +#include +#include + +// Override all stb_truetype dependencies before including the implementation + +#define STBTT_ifloor(x) ((int) stb_floor(x)) +#define STBTT_iceil(x) ((int) stb_ceil(x)) +#define STBTT_sqrt(x) stb_sqrt(x) +#define STBTT_pow(x,y) stb_pow(x,y) +#define STBTT_fmod(x,y) stb_fmod(x,y) +#define STBTT_cos(x) stb_cos(x) +#define STBTT_acos(x) stb_acos(x) +#define STBTT_fabs(x) stb_fabs(x) + +#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x)) +#define STBTT_free(x,u) ((void)(u), montauk::mfree(x)) + +#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n) +#define STBTT_memset(d,v,n) montauk::memset(d,v,n) + +#define STBTT_strlen(x) montauk::slen(x) + +#define STBTT_assert(x) ((void)(x)) + +#define STB_TRUETYPE_IMPLEMENTATION +#include diff --git a/programs/src/music/main.cpp b/programs/src/music/main.cpp index 8b7b60d..0cd5735 100644 --- a/programs/src/music/main.cpp +++ b/programs/src/music/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -922,6 +923,22 @@ extern "C" void _start() { g.hovered_item = -1; // Parse arguments: accept a directory path or a file path + // Helper: set dir_path to current user's home via session config + auto set_user_home = [&]() { + auto doc = montauk::config::load("session"); + const char* name = doc.get_string("session.username", ""); + if (name[0]) { + int p = 0; + const char* pfx = "0:/users/"; + while (*pfx && p < (int)sizeof(g.dir_path) - 1) g.dir_path[p++] = *pfx++; + while (*name && p < (int)sizeof(g.dir_path) - 1) g.dir_path[p++] = *name++; + g.dir_path[p] = '\0'; + } else { + memcpy(g.dir_path, "0:/home", 8); + } + doc.destroy(); + }; + char arg_file[128] = {}; { char args[256]; @@ -943,7 +960,7 @@ extern "C" void _start() { arg_file[flen] = '\0'; } } else { - memcpy(g.dir_path, "0:/home", 8); + set_user_home(); } } else { int len = montauk::slen(args); @@ -952,7 +969,7 @@ extern "C" void _start() { g.dir_path[len] = '\0'; } } else { - memcpy(g.dir_path, "0:/home", 8); + set_user_home(); } } diff --git a/programs/src/shell/Makefile b/programs/src/shell/Makefile new file mode 100644 index 0000000..d52cb28 --- /dev/null +++ b/programs/src/shell/Makefile @@ -0,0 +1,89 @@ +# Makefile for shell (interactive shell) on MontaukOS +# Copyright (c) 2025-2026 Daniel Hammer + +MAKEFLAGS += -rR +.SUFFIXES: + +# ---- Toolchain ---- + +TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf- +ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),) + CXX := $(TOOLCHAIN_PREFIX)g++ +else + CXX := g++ +endif + +# ---- Paths ---- + +PROG_INC := ../../include +LINK_LD := ../../link.ld +BINDIR := ../../bin +OBJDIR := obj + +# ---- C++ compiler flags ---- + +CXXFLAGS := \ + -std=gnu++20 \ + -g -O2 -pipe \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -nostdinc \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -fno-PIC \ + -fno-rtti \ + -fno-exceptions \ + -ffunction-sections \ + -fdata-sections \ + -m64 \ + -march=x86-64 \ + -mno-80387 \ + -mno-mmx \ + -mno-sse \ + -mno-sse2 \ + -mno-red-zone \ + -mcmodel=small \ + -MMD -MP \ + -I . \ + -I $(PROG_INC) \ + -isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \ + -isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include + +# ---- Linker flags ---- + +LDFLAGS := \ + -nostdlib \ + -static \ + -Wl,--build-id=none \ + -Wl,--gc-sections \ + -Wl,-m,elf_x86_64 \ + -z max-page-size=0x1000 \ + -T $(LINK_LD) + +# ---- Source files ---- + +SRCS := main.cpp vars.cpp builtins.cpp exec.cpp +OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o)) + +# ---- Target ---- + +TARGET := $(BINDIR)/os/shell.elf + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJS) $(LINK_LD) Makefile + mkdir -p $(BINDIR)/os + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +$(OBJDIR)/%.o: %.cpp shell.h Makefile + mkdir -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +-include $(OBJS:.o=.d) + +clean: + rm -rf $(OBJDIR) $(TARGET) diff --git a/programs/src/shell/builtins.cpp b/programs/src/shell/builtins.cpp new file mode 100644 index 0000000..56328d6 --- /dev/null +++ b/programs/src/shell/builtins.cpp @@ -0,0 +1,275 @@ +/* + * builtins.cpp + * Shell builtin commands: help, ls, cd, man + * Copyright (c) 2025-2026 Daniel Hammer +*/ + +#include "shell.h" + +// ---- help ---- + +void cmd_help() { + montauk::print("Shell builtins:\n"); + montauk::print(" help Show this help message\n"); + montauk::print(" ls [dir] List files in directory\n"); + montauk::print(" cd [dir] Change working directory\n"); + montauk::print(" pwd Print working directory\n"); + montauk::print(" echo [-n] ... Print arguments\n"); + montauk::print(" set [VAR=val] Show or set shell variables\n"); + montauk::print(" unset VAR Remove a shell variable\n"); + montauk::print(" true / false Return success / failure\n"); + montauk::print(" N: Switch to drive N (e.g. 1:)\n"); + montauk::print(" exit Exit the shell\n"); + montauk::print("\n"); + montauk::print("Syntax:\n"); + montauk::print(" VAR=value Set a shell variable\n"); + montauk::print(" $VAR ${VAR} Variable expansion\n"); + montauk::print(" ~ Expands to home directory\n"); + montauk::print(" cmd1 ; cmd2 Run commands sequentially\n"); + montauk::print(" cmd1 && cmd2 Run cmd2 if cmd1 succeeds\n"); + montauk::print(" cmd1 || cmd2 Run cmd2 if cmd1 fails\n"); + montauk::print(" # comment Comment (ignored)\n"); + montauk::print("\n"); + montauk::print("Built-in variables:\n"); + montauk::print(" $USER $HOME $PWD $?\n"); + montauk::print("\n"); + montauk::print("System commands:\n"); + montauk::print(" man View manual pages\n"); + montauk::print(" cat Display file contents\n"); + montauk::print(" edit [file] Text editor\n"); + montauk::print(" whoami Print current username\n"); + montauk::print(" info Show system information\n"); + montauk::print(" date Show current date and time\n"); + montauk::print(" uptime Show uptime\n"); + montauk::print(" clear Clear the screen\n"); + montauk::print(" fontscale [n] Set terminal font scale (1-8)\n"); + montauk::print(" reset Reboot the system\n"); + montauk::print(" shutdown Shut down the system\n"); + montauk::print("\n"); + montauk::print("Network commands:\n"); + montauk::print(" ping Send ICMP echo requests\n"); + montauk::print(" nslookup DNS lookup\n"); + montauk::print(" ifconfig Show/set network configuration\n"); + montauk::print(" tcpconnect Connect to a TCP server\n"); + montauk::print(" irc IRC client\n"); + montauk::print(" dhcp DHCP client\n"); + montauk::print(" fetch HTTP client\n"); + montauk::print(" httpd HTTP server\n"); + montauk::print("\n"); + montauk::print("Games:\n"); + montauk::print(" doom DOOM\n"); + montauk::print("\n"); + montauk::print("Any .elf on the ramdisk is executable.\n"); +} + +// ---- ls ---- + +void cmd_ls(const char* arg) { + arg = skip_spaces(arg); + + char dir[128]; + int drive = current_drive; + if (*arg) { + if (has_drive_prefix(arg)) { + drive = parse_drive_prefix(arg); + int plen = drive_prefix_len(arg); + scopy(dir, arg + plen + 1, sizeof(dir)); + } else if (arg[0] == '/') { + scopy(dir, arg + 1, sizeof(dir)); + } else if (cwd[0]) { + scopy(dir, cwd, sizeof(dir)); + scat(dir, "/", sizeof(dir)); + scat(dir, arg, sizeof(dir)); + } else { + scopy(dir, arg, sizeof(dir)); + } + } else { + scopy(dir, cwd, sizeof(dir)); + } + + char path[128]; + build_drive_path(drive, dir, path, sizeof(path)); + + const char* entries[64]; + int count = montauk::readdir(path, entries, 64); + if (count <= 0) { + montauk::print("(empty)\n"); + return; + } + + int prefixLen = 0; + if (dir[0]) prefixLen = slen(dir) + 1; + + for (int i = 0; i < count; i++) { + montauk::print(" "); + if (prefixLen > 0 && starts_with(entries[i], dir)) { + montauk::print(entries[i] + prefixLen); + } else { + montauk::print(entries[i]); + } + montauk::putchar('\n'); + } +} + +// ---- cd ---- + +bool switch_drive(int drive) { + char path[8]; + build_drive_path(drive, "", path, sizeof(path)); + const char* entries[1]; + if (montauk::readdir(path, entries, 1) < 0) return false; + current_drive = drive; + cwd[0] = '\0'; + return true; +} + +int cmd_cd(const char* arg) { + arg = skip_spaces(arg); + + // cd with no argument -> go to home directory (or root if no session) + if (*arg == '\0') { + if (session_home[0] && has_drive_prefix(session_home)) { + int drive = parse_drive_prefix(session_home); + int plen = drive_prefix_len(session_home); + const char* rel = session_home + plen; + if (*rel == '/') rel++; + current_drive = drive; + if (*rel) scopy(cwd, rel, sizeof(cwd)); + else cwd[0] = '\0'; + } else { + cwd[0] = '\0'; + } + return 0; + } + + // cd / -> go to root + if (streq(arg, "/")) { + cwd[0] = '\0'; + return 0; + } + + // Strip trailing slashes from argument + static char argBuf[128]; + int aLen = 0; + while (arg[aLen] && aLen < 127) { argBuf[aLen] = arg[aLen]; aLen++; } + argBuf[aLen] = '\0'; + while (aLen > 0 && argBuf[aLen - 1] == '/') argBuf[--aLen] = '\0'; + arg = argBuf; + + if (*arg == '\0') { + cwd[0] = '\0'; + return 0; + } + + // cd .. -> go up one level + if (streq(arg, "..")) { + int len = slen(cwd); + int last = -1; + for (int i = 0; i < len; i++) { + if (cwd[i] == '/') last = i; + } + if (last >= 0) { + cwd[last] = '\0'; + } else { + cwd[0] = '\0'; + } + return 0; + } + + // cd /path -> absolute path from root + if (arg[0] == '/') { + arg++; + if (*arg == '\0') { cwd[0] = '\0'; return 0; } + char path[128]; + build_dir_path(arg, path, sizeof(path)); + const char* entries[1]; + if (montauk::readdir(path, entries, 1) < 0) { + montauk::print("cd: no such directory: "); + montauk::print(arg); + montauk::putchar('\n'); + return 1; + } + scopy(cwd, arg, sizeof(cwd)); + return 0; + } + + // cd N:/ or cd N:/path -> switch drive + if (has_drive_prefix(arg)) { + int drive = parse_drive_prefix(arg); + int plen = drive_prefix_len(arg); + const char* rel = arg + plen; + if (*rel == '/') rel++; + + char rootPath[8]; + build_drive_path(drive, "", rootPath, sizeof(rootPath)); + const char* rootEntries[1]; + if (montauk::readdir(rootPath, rootEntries, 1) < 0) { + montauk::print("cd: no such drive: "); + montauk::print(arg); + montauk::putchar('\n'); + return 1; + } + + if (*rel != '\0') { + char path[128]; + build_drive_path(drive, rel, path, sizeof(path)); + const char* entries[1]; + if (montauk::readdir(path, entries, 1) < 0) { + montauk::print("cd: no such directory: "); + montauk::print(arg); + montauk::putchar('\n'); + return 1; + } + current_drive = drive; + scopy(cwd, rel, sizeof(cwd)); + } else { + current_drive = drive; + cwd[0] = '\0'; + } + return 0; + } + + // Relative path + char target[128]; + if (cwd[0]) { + scopy(target, cwd, sizeof(target)); + scat(target, "/", sizeof(target)); + scat(target, arg, sizeof(target)); + } else { + scopy(target, arg, sizeof(target)); + } + + char path[128]; + build_dir_path(target, path, sizeof(path)); + const char* entries[1]; + int count = montauk::readdir(path, entries, 1); + if (count < 0) { + montauk::print("cd: no such directory: "); + montauk::print(arg); + montauk::putchar('\n'); + return 1; + } + + scopy(cwd, target, sizeof(cwd)); + return 0; +} + +// ---- man ---- + +int cmd_man(const char* arg) { + arg = skip_spaces(arg); + if (*arg == '\0') { + montauk::print("Usage: man \n"); + montauk::print(" man
    \n"); + montauk::print("Try: man intro\n"); + return 1; + } + + int pid = montauk::spawn("0:/os/man.elf", arg); + if (pid < 0) { + montauk::print("Error: failed to start man viewer\n"); + return 1; + } + montauk::waitpid(pid); + return 0; +} diff --git a/programs/src/shell/exec.cpp b/programs/src/shell/exec.cpp new file mode 100644 index 0000000..e94dc9a --- /dev/null +++ b/programs/src/shell/exec.cpp @@ -0,0 +1,124 @@ +/* + * exec.cpp + * External command search and execution + * Copyright (c) 2025-2026 Daniel Hammer +*/ + +#include "shell.h" + +// ---- Try to spawn an ELF at the given path ---- + +static bool try_exec(const char* path, const char* args) { + int h = montauk::open(path); + if (h < 0) return false; + montauk::close(h); + + int pid = montauk::spawn(path, args); + if (pid < 0) return false; + montauk::waitpid(pid); + return true; +} + +// ---- Resolve arguments: expand relative file paths against CWD ---- + +static void resolve_args(const char* args, char* out, int outMax) { + if (!args || !args[0]) { out[0] = '\0'; return; } + + int o = 0; + const char* p = args; + + while (*p && o < outMax - 1) { + while (*p == ' ' && o < outMax - 1) { out[o++] = *p++; } + if (!*p) break; + + const char* tokStart = p; + int tokLen = 0; + while (p[tokLen] && p[tokLen] != ' ') tokLen++; + + bool resolve = (cwd[0] || current_drive != 0) && !has_drive_prefix(tokStart) && tokStart[0] != '-'; + + if (resolve) { + char candidate[256]; + int r = 0; + if (current_drive >= 10) candidate[r++] = '0' + current_drive / 10; + candidate[r++] = '0' + current_drive % 10; + candidate[r++] = ':'; candidate[r++] = '/'; + int j = 0; + while (cwd[j] && r < 255) candidate[r++] = cwd[j++]; + if (cwd[0] && r < 255) candidate[r++] = '/'; + for (int k = 0; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k]; + candidate[r] = '\0'; + + int h = montauk::open(candidate); + if (h >= 0) { + montauk::close(h); + for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k]; + } else { + bool looksLikeFile = false; + for (int k = 0; k < tokLen; k++) { + if (tokStart[k] == '.') { looksLikeFile = true; break; } + } + if (looksLikeFile) { + for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k]; + } else { + for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; + } + } + } else { + for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; + } + + p = tokStart + tokLen; + } + out[o] = '\0'; +} + +// ---- Search and execute an external command ---- + +int exec_external(const char* cmd, const char* args) { + char path[256]; + + char resolvedArgs[512]; + resolve_args(args, resolvedArgs, sizeof(resolvedArgs)); + const char* finalArgs = resolvedArgs[0] ? resolvedArgs : nullptr; + + // 1. Try 0:/os/.elf + scopy(path, "0:/os/", sizeof(path)); + scat(path, cmd, sizeof(path)); + scat(path, ".elf", sizeof(path)); + if (try_exec(path, finalArgs)) return 0; + + // 2. Try 0:/games/.elf + scopy(path, "0:/games/", sizeof(path)); + scat(path, cmd, sizeof(path)); + scat(path, ".elf", sizeof(path)); + if (try_exec(path, finalArgs)) return 0; + + // 3. Try N://.elf on current drive + if (cwd[0]) { + build_drive_path(current_drive, "", path, sizeof(path)); + scat(path, cwd, sizeof(path)); + scat(path, "/", sizeof(path)); + scat(path, cmd, sizeof(path)); + scat(path, ".elf", sizeof(path)); + if (try_exec(path, finalArgs)) return 0; + } + + // 4. Try N:/.elf on current drive + build_drive_path(current_drive, "", path, sizeof(path)); + scat(path, cmd, sizeof(path)); + scat(path, ".elf", sizeof(path)); + if (try_exec(path, finalArgs)) return 0; + + // 5. If on a non-zero drive, also try 0:/.elf + if (current_drive != 0) { + scopy(path, "0:/", sizeof(path)); + scat(path, cmd, sizeof(path)); + scat(path, ".elf", sizeof(path)); + if (try_exec(path, finalArgs)) return 0; + } + + montauk::print(cmd); + montauk::print(": command not found\n"); + return 127; +} diff --git a/programs/src/shell/main.cpp b/programs/src/shell/main.cpp index b4c1977..56dcfe6 100644 --- a/programs/src/shell/main.cpp +++ b/programs/src/shell/main.cpp @@ -1,75 +1,30 @@ /* * main.cpp - * Interactive shell for MontaukOS - * Copyright (c) 2025 Daniel Hammer + * Entry point, input loop, command dispatch, and chaining + * Copyright (c) 2025-2026 Daniel Hammer */ -#include -#include +#include "shell.h" -using montauk::slen; -using montauk::streq; -using montauk::starts_with; -using montauk::skip_spaces; +// ---- Shared state definitions ---- -static void scopy(char* dst, const char* src, int maxLen) { - int i = 0; - while (src[i] && i < maxLen - 1) { dst[i] = src[i]; i++; } - dst[i] = '\0'; -} +char cwd[128] = ""; +int current_drive = 0; +int last_exit = 0; +char session_user[32] = ""; +char session_home[64] = ""; -static void scat(char* dst, const char* src, int maxLen) { - int dLen = slen(dst); - int i = 0; - while (src[i] && dLen + i < maxLen - 1) { - dst[dLen + i] = src[i]; - i++; +// ---- Session info (read once at startup) ---- + +void read_session() { + auto doc = montauk::config::load("session"); + const char* name = doc.get_string("session.username", ""); + if (name[0]) { + scopy(session_user, name, sizeof(session_user)); + scopy(session_home, "0:/users/", sizeof(session_home)); + scat(session_home, session_user, sizeof(session_home)); } - dst[dLen + i] = '\0'; -} - -// Current working directory (relative to N:/). -// "" = root, "man" = 0:/man, "man/sub" = 0:/man/sub -static char cwd[128] = ""; -static int current_drive = 0; - -// Build VFS path with explicit drive number -static void build_drive_path(int drive, const char* dir, char* out, int outMax) { - int i = 0; - if (drive >= 10) { out[i++] = '0' + drive / 10; } - out[i++] = '0' + drive % 10; - out[i++] = ':'; out[i++] = '/'; - if (dir && dir[0]) { - int j = 0; - while (dir[j] && i < outMax - 1) out[i++] = dir[j++]; - } - out[i] = '\0'; -} - -// Build VFS directory path: "N:/" or "N:/" using current_drive -static void build_dir_path(const char* dir, char* out, int outMax) { - build_drive_path(current_drive, dir, out, outMax); -} - -// Parse drive number from a drive prefix like "0:" or "12:". Returns -1 if invalid. -static int parse_drive_prefix(const char* s) { - if (s[0] < '0' || s[0] > '9') return -1; - int n = s[0] - '0'; - if (s[1] >= '0' && s[1] <= '9') { - n = n * 10 + (s[1] - '0'); - if (s[2] != ':') return -1; - } else if (s[1] == ':') { - // single digit drive - } else { - return -1; - } - return n; -} - -// Length of drive prefix ("0:" = 2, "12:" = 3). Assumes valid prefix. -static int drive_prefix_len(const char* s) { - if (s[1] >= '0' && s[1] <= '9') return 3; // e.g. "12:" - return 2; // e.g. "0:" + doc.destroy(); } // ---- Command history ---- @@ -77,11 +32,10 @@ static int drive_prefix_len(const char* s) { static constexpr int HISTORY_MAX = 32; static char history[HISTORY_MAX][256]; static int history_count = 0; -static int history_next = 0; // ring-buffer write index +static int history_next = 0; static void history_add(const char* line) { if (line[0] == '\0') return; - // Don't add duplicate of last entry if (history_count > 0) { int prev = (history_next + HISTORY_MAX - 1) % HISTORY_MAX; if (streq(history[prev], line)) return; @@ -91,7 +45,6 @@ static void history_add(const char* line) { if (history_count < HISTORY_MAX) history_count++; } -// Get history entry by index (0 = most recent, 1 = one before that, ...) static const char* history_get(int idx) { if (idx < 0 || idx >= history_count) return nullptr; int pos = (history_next + HISTORY_MAX - 1 - idx) % HISTORY_MAX; @@ -116,17 +69,14 @@ static void prompt() { montauk::print("> "); } -// ---- Erase current input line on screen ---- +// ---- Line editing ---- static void erase_input(int len) { - // Move cursor to start of input and overwrite with spaces for (int i = 0; i < len; i++) montauk::putchar('\b'); for (int i = 0; i < len; i++) montauk::putchar(' '); for (int i = 0; i < len; i++) montauk::putchar('\b'); } -// ---- Replace visible line with new content ---- - static void replace_line(char* line, int* pos, const char* newContent) { int oldLen = *pos; erase_input(oldLen); @@ -140,386 +90,43 @@ static void replace_line(char* line, int* pos, const char* newContent) { *pos = newLen; } -// ---- Builtin: help ---- +// ---- Command dispatch (single command, already expanded) ---- -static void cmd_help() { - montauk::print("Shell builtins:\n"); - montauk::print(" help Show this help message\n"); - montauk::print(" ls [dir] List files in directory\n"); - montauk::print(" cd [dir] Change working directory\n"); - montauk::print(" N: Switch to drive N (e.g. 1:)\n"); - montauk::print(" exit Exit the shell\n"); - montauk::print("\n"); - montauk::print("System commands:\n"); - montauk::print(" man View manual pages\n"); - montauk::print(" cat Display file contents\n"); - montauk::print(" edit [file] Text editor\n"); - montauk::print(" info Show system information\n"); - montauk::print(" date Show current date and time\n"); - montauk::print(" uptime Show uptime\n"); - montauk::print(" clear Clear the screen\n"); - montauk::print(" fontscale [n] Set terminal font scale (1-8)\n"); - montauk::print(" reset Reboot the system\n"); - montauk::print(" shutdown Shut down the system\n"); - montauk::print("\n"); - montauk::print("Network commands:\n"); - montauk::print(" ping Send ICMP echo requests\n"); - montauk::print(" nslookup DNS lookup\n"); - montauk::print(" ifconfig Show/set network configuration\n"); - montauk::print(" tcpconnect Connect to a TCP server\n"); - montauk::print(" irc IRC client\n"); - montauk::print(" dhcp DHCP client\n"); - montauk::print(" fetch HTTP client\n"); - montauk::print(" httpd HTTP server\n"); - montauk::print("\n"); - montauk::print("Games:\n"); - montauk::print(" doom DOOM\n"); - montauk::print("\n"); - montauk::print("Any .elf on the ramdisk is executable.\n"); -} - -// Check if a string already has a VFS drive prefix (e.g. "0:/" or "12:/") -static bool has_drive_prefix(const char* s) { - return parse_drive_prefix(s) >= 0; -} - -// ---- Builtin: ls ---- - -static void cmd_ls(const char* arg) { - arg = skip_spaces(arg); - - // Build the target directory (relative path from root) - char dir[128]; - int drive = current_drive; - if (*arg) { - if (has_drive_prefix(arg)) { - // Absolute VFS path: "N:/something" - drive = parse_drive_prefix(arg); - int plen = drive_prefix_len(arg); - scopy(dir, arg + plen + 1, sizeof(dir)); // skip "N:/" - } else if (arg[0] == '/') { - // Absolute path from root: "/something" - scopy(dir, arg + 1, sizeof(dir)); - } else if (cwd[0]) { - // Relative path with CWD - scopy(dir, cwd, sizeof(dir)); - scat(dir, "/", sizeof(dir)); - scat(dir, arg, sizeof(dir)); - } else { - // Relative path at root - scopy(dir, arg, sizeof(dir)); - } - } else { - // ls with no arg -- use cwd - scopy(dir, cwd, sizeof(dir)); - } - - char path[128]; - build_drive_path(drive, dir, path, sizeof(path)); - - const char* entries[64]; - int count = montauk::readdir(path, entries, 64); - if (count <= 0) { - montauk::print("(empty)\n"); - return; - } - - // Prefix to strip: "dir/" (if dir is non-empty) - int prefixLen = 0; - if (dir[0]) prefixLen = slen(dir) + 1; - - for (int i = 0; i < count; i++) { - montauk::print(" "); - if (prefixLen > 0 && starts_with(entries[i], dir)) { - montauk::print(entries[i] + prefixLen); - } else { - montauk::print(entries[i]); - } - montauk::putchar('\n'); - } -} - -// ---- Builtin: cd ---- - -// Switch to a drive. Returns true if valid. -static bool switch_drive(int drive) { - // Validate drive exists by trying to readdir its root - char path[8]; - build_drive_path(drive, "", path, sizeof(path)); - const char* entries[1]; - if (montauk::readdir(path, entries, 1) < 0) return false; - current_drive = drive; - cwd[0] = '\0'; - return true; -} - -static void cmd_cd(const char* arg) { - arg = skip_spaces(arg); - - // Strip trailing slashes from argument (ls shows dirs as "www/", user may type that) - static char argBuf[128]; - int aLen = 0; - while (arg[aLen] && aLen < 127) { argBuf[aLen] = arg[aLen]; aLen++; } - argBuf[aLen] = '\0'; - while (aLen > 0 && argBuf[aLen - 1] == '/') argBuf[--aLen] = '\0'; - arg = argBuf; - - // cd or cd / -> go to root - if (*arg == '\0' || streq(arg, "/")) { - cwd[0] = '\0'; - return; - } - - // cd .. -> go up one level - if (streq(arg, "..")) { - int len = slen(cwd); - int last = -1; - for (int i = 0; i < len; i++) { - if (cwd[i] == '/') last = i; - } - if (last >= 0) { - cwd[last] = '\0'; - } else { - cwd[0] = '\0'; - } - return; - } - - // cd /path -> absolute path from root - if (arg[0] == '/') { - arg++; - if (*arg == '\0') { cwd[0] = '\0'; return; } - char path[128]; - build_dir_path(arg, path, sizeof(path)); - const char* entries[1]; - if (montauk::readdir(path, entries, 1) < 0) { - montauk::print("cd: no such directory: "); - montauk::print(arg); - montauk::putchar('\n'); - return; - } - scopy(cwd, arg, sizeof(cwd)); - return; - } - - // cd N:/ or cd N:/path -> switch drive and optionally cd into path - if (has_drive_prefix(arg)) { - int drive = parse_drive_prefix(arg); - int plen = drive_prefix_len(arg); - const char* rel = arg + plen; // points at ":/" or ":" - if (*rel == '/') rel++; // skip the '/' - - // Validate drive exists - char rootPath[8]; - build_drive_path(drive, "", rootPath, sizeof(rootPath)); - const char* rootEntries[1]; - if (montauk::readdir(rootPath, rootEntries, 1) < 0) { - montauk::print("cd: no such drive: "); - montauk::print(arg); - montauk::putchar('\n'); - return; - } - - // If there's a path after the drive, validate it - if (*rel != '\0') { - char path[128]; - build_drive_path(drive, rel, path, sizeof(path)); - const char* entries[1]; - if (montauk::readdir(path, entries, 1) < 0) { - montauk::print("cd: no such directory: "); - montauk::print(arg); - montauk::putchar('\n'); - return; - } - current_drive = drive; - scopy(cwd, rel, sizeof(cwd)); - } else { - current_drive = drive; - cwd[0] = '\0'; - } - return; - } - - // Build target directory path (relative to CWD) - char target[128]; - if (cwd[0]) { - scopy(target, cwd, sizeof(target)); - scat(target, "/", sizeof(target)); - scat(target, arg, sizeof(target)); - } else { - scopy(target, arg, sizeof(target)); - } - - // Validate: try readdir on the target - char path[128]; - build_dir_path(target, path, sizeof(path)); - const char* entries[1]; - int count = montauk::readdir(path, entries, 1); - if (count < 0) { - montauk::print("cd: no such directory: "); - montauk::print(arg); - montauk::putchar('\n'); - return; - } - - // Set cwd - scopy(cwd, target, sizeof(cwd)); -} - -// ---- Builtin: man ---- - -static void cmd_man(const char* arg) { - arg = skip_spaces(arg); - if (*arg == '\0') { - montauk::print("Usage: man \n"); - montauk::print(" man
    \n"); - montauk::print("Try: man intro\n"); - return; - } - - int pid = montauk::spawn("0:/os/man.elf", arg); - if (pid < 0) { - montauk::print("Error: failed to start man viewer\n"); - } else { - montauk::waitpid(pid); - } -} - -// ---- External command execution ---- - -// Try to spawn an ELF at the given path. Returns true on success. -static bool try_exec(const char* path, const char* args) { - // Check if the file exists before asking the kernel to load it - int h = montauk::open(path); - if (h < 0) return false; - montauk::close(h); - - int pid = montauk::spawn(path, args); - if (pid < 0) return false; - montauk::waitpid(pid); - return true; -} - -// Resolve arguments: expand relative file paths against CWD. -// Tokens that already have a drive prefix (e.g. "0:/foo") are left as-is. -// Everything before the first space-delimited token that looks like a path -// option (starts with '-') is also left as-is. -static void resolve_args(const char* args, char* out, int outMax) { - if (!args || !args[0]) { out[0] = '\0'; return; } - - int o = 0; - const char* p = args; - - while (*p && o < outMax - 1) { - // Skip spaces, copy them through - while (*p == ' ' && o < outMax - 1) { out[o++] = *p++; } - if (!*p) break; - - // Extract the token - const char* tokStart = p; - int tokLen = 0; - while (p[tokLen] && p[tokLen] != ' ') tokLen++; - - // Decide whether to resolve this token as a path. - // Don't resolve if it already has a drive prefix, or starts with '-' - bool resolve = (cwd[0] || current_drive != 0) && !has_drive_prefix(tokStart) && tokStart[0] != '-'; - - if (resolve) { - // Build candidate resolved path and check if the file exists - char candidate[256]; - int r = 0; - if (current_drive >= 10) candidate[r++] = '0' + current_drive / 10; - candidate[r++] = '0' + current_drive % 10; - candidate[r++] = ':'; candidate[r++] = '/'; - int j = 0; - while (cwd[j] && r < 255) candidate[r++] = cwd[j++]; - if (cwd[0] && r < 255) candidate[r++] = '/'; - for (int k = 0; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k]; - candidate[r] = '\0'; - - // Use the resolved path if the file exists. If it doesn't - // exist, still use the resolved path when the token looks - // like a filename (contains a dot) so that programs creating - // new files get the correct drive/directory prefix. - int h = montauk::open(candidate); - if (h >= 0) { - montauk::close(h); - for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k]; - } else { - bool looksLikeFile = false; - for (int k = 0; k < tokLen; k++) { - if (tokStart[k] == '.') { looksLikeFile = true; break; } - } - if (looksLikeFile) { - for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k]; - } else { - for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; - } - } - } else { - for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k]; - } - - p = tokStart + tokLen; - } - out[o] = '\0'; -} - -static void exec_external(const char* cmd, const char* args) { - char path[256]; - - // Resolve arguments against CWD so external programs get full VFS paths - char resolvedArgs[512]; - resolve_args(args, resolvedArgs, sizeof(resolvedArgs)); - const char* finalArgs = resolvedArgs[0] ? resolvedArgs : nullptr; - - // Always search drive 0 for system commands (os/, games/) - // 1. Try 0:/os/.elf - scopy(path, "0:/os/", sizeof(path)); - scat(path, cmd, sizeof(path)); - scat(path, ".elf", sizeof(path)); - if (try_exec(path, finalArgs)) return; - - // 2. Try 0:/games/.elf - scopy(path, "0:/games/", sizeof(path)); - scat(path, cmd, sizeof(path)); - scat(path, ".elf", sizeof(path)); - if (try_exec(path, finalArgs)) return; - - // 3. Try N://.elf on current drive (if cwd is set) - if (cwd[0]) { - build_drive_path(current_drive, "", path, sizeof(path)); - scat(path, cwd, sizeof(path)); - scat(path, "/", sizeof(path)); - scat(path, cmd, sizeof(path)); - scat(path, ".elf", sizeof(path)); - if (try_exec(path, finalArgs)) return; - } - - // 4. Try N:/.elf on current drive - build_drive_path(current_drive, "", path, sizeof(path)); - scat(path, cmd, sizeof(path)); - scat(path, ".elf", sizeof(path)); - if (try_exec(path, finalArgs)) return; - - // 5. If on a non-zero drive, also try 0:/.elf - if (current_drive != 0) { - scopy(path, "0:/", sizeof(path)); - scat(path, cmd, sizeof(path)); - scat(path, ".elf", sizeof(path)); - if (try_exec(path, finalArgs)) return; - } - - // Not found - montauk::print(cmd); - montauk::print(": command not found\n"); -} - -// ---- Command dispatch ---- - -static void process_command(const char* line) { +static int process_command(const char* line) { line = skip_spaces(line); - if (*line == '\0') return; + if (*line == '\0') return 0; + + // Variable assignment: NAME=VALUE + { + int eq = -1; + bool valid = (line[0] >= 'A' && line[0] <= 'Z') || + (line[0] >= 'a' && line[0] <= 'z') || line[0] == '_'; + if (valid) { + for (int i = 1; line[i]; i++) { + if (line[i] == '=') { eq = i; break; } + if (!is_var_char(line[i])) break; + } + } + if (eq > 0) { + char name[32]; + int nlen = eq < 31 ? eq : 31; + for (int i = 0; i < nlen; i++) name[i] = line[i]; + name[nlen] = '\0'; + const char* val = line + eq + 1; + int vlen = slen(val); + char vbuf[128]; + if (vlen >= 2 && ((val[0] == '"' && val[vlen-1] == '"') || + (val[0] == '\'' && val[vlen-1] == '\''))) { + int j = 0; + for (int i = 1; i < vlen - 1 && j < 127; i++) vbuf[j++] = val[i]; + vbuf[j] = '\0'; + var_set(name, vbuf); + } else { + var_set(name, val); + } + return 0; + } + } // Parse command name and arguments char cmd[128]; @@ -543,26 +150,174 @@ static void process_command(const char* line) { montauk::print("No such drive: "); montauk::print(cmd); montauk::print("/\n"); + return 1; } - return; + return 0; } // Builtins - if (streq(cmd, "help")) { - cmd_help(); - } else if (streq(cmd, "ls")) { - cmd_ls(args ? args : ""); - } else if (streq(cmd, "cd")) { - cmd_cd(args ? args : ""); - } else if (streq(cmd, "man")) { - cmd_man(args ? args : ""); - } else if (streq(cmd, "exit")) { - montauk::print("Goodbye.\n"); - montauk::exit(0); - } else { - // External command -- pass full argument string - exec_external(cmd, args); + if (streq(cmd, "help")) { cmd_help(); return 0; } + if (streq(cmd, "ls")) { cmd_ls(args ? args : ""); return 0; } + if (streq(cmd, "cd")) { return cmd_cd(args ? args : ""); } + if (streq(cmd, "man")) { return cmd_man(args ? args : ""); } + if (streq(cmd, "true")) { return 0; } + if (streq(cmd, "false")) { return 1; } + + if (streq(cmd, "pwd")) { + char path[128]; + build_dir_path(cwd, path, sizeof(path)); + montauk::print(path); + montauk::putchar('\n'); + return 0; } + + if (streq(cmd, "echo")) { + if (!args) { + montauk::putchar('\n'); + return 0; + } + bool no_newline = false; + if (starts_with(args, "-n ")) { + no_newline = true; + args = skip_spaces(args + 3); + } else if (streq(args, "-n")) { + return 0; + } + montauk::print(args); + if (!no_newline) montauk::putchar('\n'); + return 0; + } + + if (streq(cmd, "set")) { + if (!args) { + // List all variables + if (session_user[0]) { + montauk::print("USER="); + montauk::print(session_user); + montauk::putchar('\n'); + } + if (session_home[0]) { + montauk::print("HOME="); + montauk::print(session_home); + montauk::putchar('\n'); + } + char path[128]; + build_dir_path(cwd, path, sizeof(path)); + montauk::print("PWD="); + montauk::print(path); + montauk::putchar('\n'); + int vc = var_user_count(); + for (int j = 0; j < vc; j++) { + montauk::print(var_user_name(j)); + montauk::putchar('='); + montauk::print(var_user_value(j)); + montauk::putchar('\n'); + } + return 0; + } + // set VAR=value + int eq = -1; + for (int j = 0; args[j]; j++) { + if (args[j] == '=') { eq = j; break; } + } + if (eq > 0) { + char name[32]; + int nlen = eq < 31 ? eq : 31; + for (int j = 0; j < nlen; j++) name[j] = args[j]; + name[nlen] = '\0'; + var_set(name, args + eq + 1); + return 0; + } + // set VAR (show value) + const char* val = var_get(args); + if (val) { + montauk::print(args); + montauk::putchar('='); + montauk::print(val); + montauk::putchar('\n'); + } else { + montauk::print(args); + montauk::print(": not set\n"); + } + return 0; + } + + if (streq(cmd, "unset")) { + if (!args) { + montauk::print("Usage: unset \n"); + return 1; + } + var_unset(args); + return 0; + } + + if (streq(cmd, "exit")) { + montauk::print("Goodbye.\n"); + montauk::exit(last_exit); + } + + // External command + return exec_external(cmd, args); +} + +// ---- Command line execution with chaining ---- + +static void execute_line(const char* raw) { + // Step 1: expand tilde + char texp[512]; + expand_tilde(raw, texp, sizeof(texp)); + + // Step 2: expand variables + char expanded[512]; + expand_vars(texp, expanded, sizeof(expanded)); + + // Step 3: strip comments + strip_comment(expanded); + + // Step 4: split on ;, &&, || and execute with chaining logic + const char* p = expanded; + int prev = 0; + enum { OP_NONE, OP_SEMI, OP_AND, OP_OR } pending = OP_NONE; + + while (true) { + p = skip_spaces(p); + if (!*p) break; + + // Extract next command segment + char seg[256]; + int si = 0; + int op = OP_NONE; + bool in_sq = false, in_dq = false; + + while (*p && si < 255) { + if (*p == '\'' && !in_dq) { in_sq = !in_sq; seg[si++] = *p++; continue; } + if (*p == '"' && !in_sq) { in_dq = !in_dq; seg[si++] = *p++; continue; } + if (!in_sq && !in_dq) { + if (*p == ';') { op = OP_SEMI; p++; break; } + if (*p == '&' && p[1] == '&') { op = OP_AND; p += 2; break; } + if (*p == '|' && p[1] == '|') { op = OP_OR; p += 2; break; } + } + seg[si++] = *p++; + } + seg[si] = '\0'; + + // Trim trailing spaces + while (si > 0 && seg[si - 1] == ' ') seg[--si] = '\0'; + + // Decide whether to run based on pending operator + bool run = true; + if (pending == OP_AND && prev != 0) run = false; + if (pending == OP_OR && prev == 0) run = false; + + if (run && seg[0]) { + prev = process_command(seg); + } + + pending = (decltype(pending))op; + if (op == OP_NONE) break; + } + + last_exit = prev; } // ---- Arrow key scancodes ---- @@ -575,17 +330,26 @@ static constexpr uint8_t SC_RIGHT = 0x4D; // ---- Entry point ---- extern "C" void _start() { + read_session(); + montauk::print("\n"); montauk::print(" MontaukOS\n"); montauk::print(" Copyright (c) 2025-2026 Daniel Hammer\n"); montauk::print("\n"); + if (session_user[0]) { + montauk::print(" Logged in as "); + montauk::print(session_user); + montauk::putchar('\n'); + montauk::print("\n"); + } + montauk::print(" Type 'help' for available commands.\n"); montauk::print("\n"); char line[256]; int pos = 0; - int hist_nav = -1; // -1 = not navigating history + int hist_nav = -1; prompt(); @@ -603,7 +367,6 @@ extern "C" void _start() { // Arrow keys: ascii == 0, check scancode if (ev.ascii == 0) { if (ev.scancode == SC_UP) { - // Navigate to older history entry int next = hist_nav + 1; const char* entry = history_get(next); if (entry) { @@ -611,7 +374,6 @@ extern "C" void _start() { replace_line(line, &pos, entry); } } else if (ev.scancode == SC_DOWN) { - // Navigate to newer history entry if (hist_nav > 0) { hist_nav--; const char* entry = history_get(hist_nav); @@ -619,14 +381,12 @@ extern "C" void _start() { replace_line(line, &pos, entry); } } else if (hist_nav == 0) { - // Back to empty line hist_nav = -1; erase_input(pos); pos = 0; line[0] = '\0'; } } - // Left/Right arrows: ignore for now (no cursor movement within line) continue; } @@ -634,7 +394,7 @@ extern "C" void _start() { montauk::putchar('\n'); line[pos] = '\0'; history_add(line); - process_command(line); + execute_line(line); pos = 0; hist_nav = -1; prompt(); diff --git a/programs/src/shell/shell.h b/programs/src/shell/shell.h new file mode 100644 index 0000000..a79ebc3 --- /dev/null +++ b/programs/src/shell/shell.h @@ -0,0 +1,127 @@ +/* + * shell.h + * Shared declarations for the MontaukOS interactive shell + * Copyright (c) 2025-2026 Daniel Hammer +*/ + +#pragma once + +#include +#include +#include +#include + +using montauk::slen; +using montauk::streq; +using montauk::starts_with; +using montauk::skip_spaces; + +// ---- Inline string helpers ---- + +inline void scopy(char* dst, const char* src, int maxLen) { + int i = 0; + while (src[i] && i < maxLen - 1) { dst[i] = src[i]; i++; } + dst[i] = '\0'; +} + +inline void scat(char* dst, const char* src, int maxLen) { + int dLen = slen(dst); + int i = 0; + while (src[i] && dLen + i < maxLen - 1) { + dst[dLen + i] = src[i]; + i++; + } + dst[dLen + i] = '\0'; +} + +inline void int_to_str(int n, char* buf, int sz) { + if (n == 0) { buf[0] = '0'; buf[1] = '\0'; return; } + bool neg = false; + unsigned int u; + if (n < 0) { neg = true; u = (unsigned)(-n); } else { u = (unsigned)n; } + char tmp[12]; + int i = 0; + while (u > 0) { tmp[i++] = '0' + u % 10; u /= 10; } + int o = 0; + if (neg && o < sz - 1) buf[o++] = '-'; + while (i > 0 && o < sz - 1) buf[o++] = tmp[--i]; + buf[o] = '\0'; +} + +// ---- Shared state (defined in main.cpp) ---- + +extern char cwd[128]; +extern int current_drive; +extern int last_exit; +extern char session_user[32]; +extern char session_home[64]; + +// ---- Inline path helpers ---- + +inline void build_drive_path(int drive, const char* dir, char* out, int outMax) { + int i = 0; + if (drive >= 10) { out[i++] = '0' + drive / 10; } + out[i++] = '0' + drive % 10; + out[i++] = ':'; out[i++] = '/'; + if (dir && dir[0]) { + int j = 0; + while (dir[j] && i < outMax - 1) out[i++] = dir[j++]; + } + out[i] = '\0'; +} + +inline void build_dir_path(const char* dir, char* out, int outMax) { + build_drive_path(current_drive, dir, out, outMax); +} + +inline int parse_drive_prefix(const char* s) { + if (s[0] < '0' || s[0] > '9') return -1; + int n = s[0] - '0'; + if (s[1] >= '0' && s[1] <= '9') { + n = n * 10 + (s[1] - '0'); + if (s[2] != ':') return -1; + } else if (s[1] == ':') { + // single digit drive + } else { + return -1; + } + return n; +} + +inline int drive_prefix_len(const char* s) { + if (s[1] >= '0' && s[1] <= '9') return 3; + return 2; +} + +inline bool has_drive_prefix(const char* s) { + return parse_drive_prefix(s) >= 0; +} + +// ---- Variables (vars.cpp) ---- + +void var_set(const char* name, const char* value); +void var_unset(const char* name); +const char* var_get(const char* name); +bool is_var_char(char c); +void expand_vars(const char* in, char* out, int outMax); +void expand_tilde(const char* in, char* out, int outMax); +void strip_comment(char* line); +int var_user_count(); +const char* var_user_name(int idx); +const char* var_user_value(int idx); + +// ---- Session (main.cpp) ---- + +void read_session(); + +// ---- Builtins (builtins.cpp) ---- + +void cmd_help(); +void cmd_ls(const char* arg); +int cmd_cd(const char* arg); +int cmd_man(const char* arg); +bool switch_drive(int drive); + +// ---- External execution (exec.cpp) ---- + +int exec_external(const char* cmd, const char* args); diff --git a/programs/src/shell/vars.cpp b/programs/src/shell/vars.cpp new file mode 100644 index 0000000..47ff5f7 --- /dev/null +++ b/programs/src/shell/vars.cpp @@ -0,0 +1,166 @@ +/* + * vars.cpp + * Shell variable storage, expansion, and tilde/comment processing + * Copyright (c) 2025-2026 Daniel Hammer +*/ + +#include "shell.h" + +// ---- Storage ---- + +static constexpr int MAX_VARS = 32; + +struct ShellVar { + char name[32]; + char value[128]; +}; + +static ShellVar vars[MAX_VARS]; +static int var_count = 0; + +// ---- Core operations ---- + +void var_set(const char* name, const char* value) { + for (int i = 0; i < var_count; i++) { + if (streq(vars[i].name, name)) { + scopy(vars[i].value, value, sizeof(vars[i].value)); + return; + } + } + if (var_count < MAX_VARS) { + scopy(vars[var_count].name, name, sizeof(vars[var_count].name)); + scopy(vars[var_count].value, value, sizeof(vars[var_count].value)); + var_count++; + } +} + +void var_unset(const char* name) { + for (int i = 0; i < var_count; i++) { + if (streq(vars[i].name, name)) { + for (int j = i; j < var_count - 1; j++) vars[j] = vars[j + 1]; + var_count--; + return; + } + } +} + +// Get variable value. Built-in dynamic vars ($?, $PWD) are synthesized on +// demand. Returns nullptr if not found. The returned pointer for dynamic +// vars points to a static buffer overwritten on the next call. +const char* var_get(const char* name) { + // User-defined vars take priority + for (int i = 0; i < var_count; i++) { + if (streq(vars[i].name, name)) return vars[i].value; + } + // Synthesize built-in vars + static char synth[128]; + if (streq(name, "?")) { + int_to_str(last_exit, synth, sizeof(synth)); + return synth; + } + if (streq(name, "USER")) return session_user[0] ? session_user : nullptr; + if (streq(name, "HOME")) return session_home[0] ? session_home : nullptr; + if (streq(name, "PWD")) { + build_dir_path(cwd, synth, sizeof(synth)); + return synth; + } + return nullptr; +} + +// ---- Helpers used by the set builtin (main.cpp) ---- + +// The set builtin needs to iterate user-defined vars and show built-in +// vars. We expose a small iteration API rather than the raw array. + +int var_user_count() { return var_count; } + +const char* var_user_name(int idx) { + return (idx >= 0 && idx < var_count) ? vars[idx].name : nullptr; +} + +const char* var_user_value(int idx) { + return (idx >= 0 && idx < var_count) ? vars[idx].value : nullptr; +} + +// ---- Character classification ---- + +bool is_var_char(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '_'; +} + +// ---- Variable expansion ---- + +void expand_vars(const char* in, char* out, int outMax) { + int o = 0; + while (*in && o < outMax - 1) { + if (*in == '\\' && in[1] == '$') { + if (o < outMax - 1) out[o++] = '$'; + in += 2; + continue; + } + if (*in == '$') { + in++; + char name[32]; + int n = 0; + if (*in == '{') { + in++; + while (*in && *in != '}' && n < 31) name[n++] = *in++; + if (*in == '}') in++; + } else if (*in == '?') { + name[n++] = '?'; + in++; + } else { + while (is_var_char(*in) && n < 31) name[n++] = *in++; + } + name[n] = '\0'; + if (n > 0) { + const char* val = var_get(name); + if (val) { + while (*val && o < outMax - 1) out[o++] = *val++; + } + } else { + if (o < outMax - 1) out[o++] = '$'; + } + } else { + out[o++] = *in++; + } + } + out[o] = '\0'; +} + +// ---- Tilde expansion ---- + +void expand_tilde(const char* in, char* out, int outMax) { + int o = 0; + bool at_start = true; + while (*in && o < outMax - 1) { + if (at_start && *in == '~' && session_home[0]) { + if (in[1] == '\0' || in[1] == '/' || in[1] == ' ') { + const char* h = session_home; + while (*h && o < outMax - 1) out[o++] = *h++; + in++; + } else { + out[o++] = *in++; + } + } else { + at_start = (*in == ' '); + out[o++] = *in++; + } + } + out[o] = '\0'; +} + +// ---- Comment stripping ---- + +void strip_comment(char* line) { + bool in_sq = false, in_dq = false; + for (int i = 0; line[i]; i++) { + if (line[i] == '\'' && !in_dq) in_sq = !in_sq; + else if (line[i] == '"' && !in_sq) in_dq = !in_dq; + else if (line[i] == '#' && !in_sq && !in_dq) { + line[i] = '\0'; + return; + } + } +} diff --git a/programs/src/whoami/main.cpp b/programs/src/whoami/main.cpp new file mode 100644 index 0000000..a3be060 --- /dev/null +++ b/programs/src/whoami/main.cpp @@ -0,0 +1,23 @@ +/* + * main.cpp + * whoami - Print the current username + * Copyright (c) 2026 Daniel Hammer +*/ + +#include +#include +#include +#include + +extern "C" void _start() { + auto doc = montauk::config::load("session"); + const char* name = doc.get_string("session.username", ""); + if (name[0]) { + montauk::print(name); + montauk::putchar('\n'); + } else { + montauk::print("unknown\n"); + } + doc.destroy(); + montauk::exit(0); +} diff --git a/programs/src/wikipedia/main.cpp b/programs/src/wikipedia/main.cpp index ab83f0e..80ed02d 100644 --- a/programs/src/wikipedia/main.cpp +++ b/programs/src/wikipedia/main.cpp @@ -90,12 +90,14 @@ static void px_fill(uint32_t* px, int bw, int x, int y, int w, int h, Color c) { int x0 = x < 0 ? 0 : x, y0 = y < 0 ? 0 : y; int x1 = x + w, y1 = y + h; if (x1 > bw) x1 = bw; + if (y1 > g_win_h) y1 = g_win_h; for (int row = y0; row < y1; row++) for (int col = x0; col < x1; col++) px[row * bw + col] = v; } static void px_hline(uint32_t* px, int bw, int x, int y, int len, Color c) { + if (y < 0 || y >= g_win_h) return; uint32_t v = c.to_pixel(); int x1 = x + len; if (x < 0) x = 0; @@ -105,8 +107,12 @@ static void px_hline(uint32_t* px, int bw, int x, int y, int len, Color c) { } static void px_vline(uint32_t* px, int bw, int x, int y, int len, Color c) { + if (x < 0 || x >= bw) return; uint32_t v = c.to_pixel(); - for (int row = y; row < y + len; row++) + int y1 = y + len; + if (y < 0) y = 0; + if (y1 > g_win_h) y1 = g_win_h; + for (int row = y; row < y1; row++) px[row * bw + x] = v; } diff --git a/scripts/copy_icons.sh b/scripts/copy_icons.sh index 93e4793..3a7db59 100755 --- a/scripts/copy_icons.sh +++ b/scripts/copy_icons.sh @@ -90,6 +90,10 @@ ICONS=( "actions/16/media-rewind.svg" "apps/scalable/multimedia-video-player.svg" "apps/scalable/bluetooth.svg" + "panel/volume-level-high.svg" + "status/symbolic/audio-volume-high-symbolic.svg" + "apps/scalable/gnome-logout.svg" + "apps/scalable/lock.svg" ) copied=0 diff --git a/template/Makefile b/template/Makefile new file mode 100644 index 0000000..ab81dc5 --- /dev/null +++ b/template/Makefile @@ -0,0 +1,118 @@ +# Makefile for standalone MontaukOS app (template) +# Usage: +# make Build the app +# make clean Remove build artifacts +# make install Copy ELF to MontaukOS ramdisk bin directory +# +# Copy this entire directory, rename it, and edit APP_NAME/SRCS below. + +MAKEFLAGS += -rR +.SUFFIXES: + +# ---- App configuration ---- +# Change these for your app: + +APP_NAME := myapp +SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp + +# Optional features — set to 1 to enable: +# USE_TLS=1 HTTPS/TLS support (libtls + libbearssl) +# USE_JPEG=1 JPEG image decoding (libjpeg / stb_image) +USE_TLS ?= 0 +USE_JPEG ?= 0 + +# ---- Toolchain ---- +# Looks for the cross-compiler via MONTAUKOS, then falls back to system g++. + +MONTAUKOS ?= $(HOME)/dev/MontaukOS +TOOLCHAIN := $(MONTAUKOS)/toolchain/local/bin/x86_64-elf- +ifneq ($(wildcard $(TOOLCHAIN)gcc),) + CXX := $(TOOLCHAIN)g++ +else + CXX := g++ +endif + +# ---- Paths ---- + +SYSROOT := sysroot +OBJDIR := obj +BINDIR := bin +LINK_LD := link.ld + +# ---- Compiler flags ---- + +CXXFLAGS := \ + -std=gnu++20 \ + -g -O2 -pipe \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -Wno-unused-function \ + -nostdinc \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -fno-PIC \ + -fno-rtti \ + -fno-exceptions \ + -ffunction-sections \ + -fdata-sections \ + -m64 \ + -march=x86-64 \ + -msse \ + -msse2 \ + -mno-red-zone \ + -mcmodel=small \ + -I $(SYSROOT)/include \ + -I src \ + -isystem $(SYSROOT)/include/libc + +# ---- Linker flags ---- + +LDFLAGS := \ + -nostdlib \ + -static \ + -Wl,--build-id=none \ + -Wl,--gc-sections \ + -Wl,-m,elf_x86_64 \ + -z max-page-size=0x1000 \ + -T $(LINK_LD) + +# ---- Libraries ---- +# Order matters: libtls depends on libbearssl, everything depends on liblibc. + +LIBS := +ifeq ($(USE_TLS),1) + LIBS += $(SYSROOT)/lib/libtls.a $(SYSROOT)/lib/libbearssl.a +endif +ifeq ($(USE_JPEG),1) + LIBS += $(SYSROOT)/lib/libjpeg.a +endif +LIBS += $(SYSROOT)/lib/liblibc.a + +# ---- Build rules ---- + +OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o)) +TARGET := $(BINDIR)/$(APP_NAME).elf + +.PHONY: all clean install + +all: $(TARGET) + +$(TARGET): $(OBJS) $(LINK_LD) Makefile + @mkdir -p $(BINDIR) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ + @echo "Built: $@" + +$(OBJDIR)/%.o: %.cpp Makefile + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + rm -rf $(OBJDIR) $(BINDIR) + +# Copy the built ELF into the MontaukOS ramdisk tree for testing. +install: $(TARGET) + @mkdir -p $(MONTAUKOS)/programs/bin/apps/$(APP_NAME) + cp $(TARGET) $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/$(APP_NAME).elf + @echo "Installed to $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/" diff --git a/template/README.md b/template/README.md new file mode 100644 index 0000000..7ff0a89 --- /dev/null +++ b/template/README.md @@ -0,0 +1,69 @@ +# MontaukOS App Template + +Self-contained development environment for building standalone MontaukOS GUI apps. Copy this entire directory anywhere and start building. + +## Quick Start + +```bash +cp -r template/ ~/dev/myapp/ +cd ~/dev/myapp/ +# Edit APP_NAME and SRCS in Makefile +make +make install # copy ELF to MontaukOS ramdisk +``` + +## Build Commands + +```bash +make # GUI-only app +make USE_TLS=1 # With HTTPS/TLS (libtls + libbearssl) +make USE_JPEG=1 # With JPEG decoding (libjpeg) +make USE_TLS=1 USE_JPEG=1 # Both +make clean # Remove build artifacts +make install # Copy ELF to MontaukOS ramdisk +``` + +If the MontaukOS tree is not at `~/dev/MontaukOS/`, pass the path to the cross-compiler: + +```bash +make MONTAUKOS=/path/to/MontaukOS +``` + +## Structure + +``` +myapp/ +├── Makefile Edit APP_NAME and SRCS here +├── link.ld Linker script (load at 0x400000) +├── src/ +│ ├── main.cpp Your app (template with window, rendering, input) +│ ├── stb_truetype_impl.cpp TrueType font support (keep this) +│ └── cxxrt.cpp C++ new/delete runtime (keep this) +├── sysroot/ +│ ├── include/ +│ │ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h +│ │ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ... +│ │ ├── http/ http.hpp (HTTP GET/POST/etc. wrapper) +│ │ ├── tls/ tls.hpp (HTTPS/TLS, for USE_TLS=1) +│ │ ├── Api/ Syscall.hpp (low-level syscall numbers) +│ │ ├── libc/ stdio.h, stdlib.h, string.h, ... +│ │ ├── bearssl*.h BearSSL headers (for USE_TLS=1) +│ │ └── (freestanding C/C++ standard headers) +│ └── lib/ +│ ├── liblibc.a C library (always linked) +│ ├── libtls.a TLS helper library +│ ├── libbearssl.a BearSSL crypto +│ └── libjpeg.a JPEG decoding (stb_image) +└── docs/ + ├── gui-apps.md GUI programming guide + └── syscalls.md Syscall and API reference +``` + +## Key Points + +- Entry point: `extern "C" void _start()` (not `main`) +- Memory: `montauk::malloc()` / `montauk::mfree()` (no standard libc) +- Window: `win_create()` / `win_poll()` / `win_present()` / `win_destroy()` +- Fonts: `TrueTypeFont::init("0:/fonts/Roboto-Medium.ttf")` +- HTTP: `#include ` with `USE_TLS=1` (see docs/) +- No exceptions, no RTTI, 32 KiB user stack diff --git a/template/docs/gui-apps.md b/template/docs/gui-apps.md new file mode 100644 index 0000000..9e76e56 --- /dev/null +++ b/template/docs/gui-apps.md @@ -0,0 +1,916 @@ +# Writing GUI Applications for MontaukOS + +This guide covers how to build graphical applications for MontaukOS, from standalone Window Server clients to desktop-integrated apps. + +## Table of Contents + +- [App Types](#app-types) +- [Standalone Window Server Apps](#standalone-window-server-apps) +- [Desktop-Integrated Apps](#desktop-integrated-apps) +- [Drawing and Rendering](#drawing-and-rendering) +- [Text and Fonts](#text-and-fonts) +- [Input Handling](#input-handling) +- [Widgets](#widgets) +- [Colors and Theming](#colors-and-theming) +- [Memory Management](#memory-management) +- [Networking and HTTPS](#networking-and-https) +- [App Manifests](#app-manifests) +- [Build System](#build-system) + +--- + +## App Types + +MontaukOS supports two kinds of GUI applications: + +| | Standalone Apps | Desktop Apps | +|---|---|---| +| **Location** | `programs/src//` | `programs/src/desktop/apps/` | +| **Window** | Own process, shared-memory pixel buffer | Embedded in desktop compositor | +| **Event loop** | `win_poll()` syscall | Callback-driven (`on_draw`, `on_mouse`, `on_key`) | +| **Drawing** | Direct pixel buffer writes | `Canvas` abstraction | +| **Examples** | Spreadsheet, Music, Wikipedia | Calculator, File Manager, Terminal | + +**Choose standalone** when you need a separate process (e.g., networking, heavy computation, isolation). **Choose desktop-integrated** for lightweight tools that benefit from tight compositor integration. + +--- + +## Standalone Window Server Apps + +Standalone apps are separate ELF binaries that communicate with the Window Server through syscalls. They get a shared-memory pixel buffer and manage their own event loop. + +### Minimal Example + +```cpp +#include +#include +#include +#include +#include + +static TrueTypeFont* g_font; +static int g_win_w, g_win_h; + +static void render(uint32_t* pixels) { + // Clear background + for (int i = 0; i < g_win_w * g_win_h; i++) + pixels[i] = Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel(); + + // Draw text + if (g_font) + g_font->draw_to_buffer(pixels, g_win_w, g_win_h, + 20, 30, "Hello, MontaukOS!", + Color::from_rgb(0x33, 0x33, 0x33), 18); +} + +extern "C" void _start() { + // Load font + g_font = new TrueTypeFont(); + g_font->init("0:/fonts/Roboto-Medium.ttf"); + + // Create window + g_win_w = 400; + g_win_h = 300; + Montauk::WinCreateResult wres; + montauk::win_create("My App", g_win_w, g_win_h, &wres); + int win_id = wres.id; + uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa; + + // Initial render + render(pixels); + montauk::win_present(win_id); + + // Event loop + while (true) { + Montauk::WinEvent ev; + int r = montauk::win_poll(win_id, &ev); + + if (r < 0) break; // Window destroyed externally + if (r == 0) { + montauk::sleep_ms(16); // ~60 FPS idle + continue; + } + + if (ev.type == 3) break; // Close event + + if (ev.type == 2) { // Resize + g_win_w = ev.resize.w; + g_win_h = ev.resize.h; + pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h); + } + + if (ev.type == 0) { // Keyboard + // ev.key.ascii, ev.key.scancode, ev.key.pressed + } + + if (ev.type == 1) { // Mouse + // ev.mouse.x, ev.mouse.y, ev.mouse.buttons + } + + render(pixels); + montauk::win_present(win_id); + } + + montauk::win_destroy(win_id); + montauk::exit(0); +} +``` + +### Window Lifecycle + +``` +win_create() Create window, get pixel buffer pointer + | + v +win_present() Push current pixel buffer to screen + | + v +win_poll() Receive events (returns 0 if none, <0 if closed) + | + v +win_resize() Handle resize, get new pixel buffer pointer + | + v +win_destroy() Clean up window +``` + +### Event Types + +Events are delivered via `win_poll()` into a `WinEvent` struct: + +| `ev.type` | Event | Fields | +|---|---|---| +| 0 | Keyboard | `ev.key.scancode`, `ev.key.ascii`, `ev.key.pressed`, `ev.key.shift`, `ev.key.ctrl`, `ev.key.alt` | +| 1 | Mouse | `ev.mouse.x`, `ev.mouse.y`, `ev.mouse.buttons`, `ev.mouse.prev_buttons`, `ev.mouse.scroll` | +| 2 | Resize | `ev.resize.w`, `ev.resize.h` | +| 3 | Close | (none) | + +### Drawing Helpers + +Standalone apps typically define local pixel-drawing helpers since they work with raw `uint32_t*` buffers: + +```cpp +static void px_fill(uint32_t* px, int bw, int bh, + int x, int y, int w, int h, uint32_t color) { + for (int row = y; row < y + h && row < bh; row++) + for (int col = x; col < x + w && col < bw; col++) + px[row * bw + col] = color; +} + +static void px_hline(uint32_t* px, int bw, int bh, + int x, int y, int w, uint32_t color) { + for (int col = x; col < x + w && col < bw; col++) + if (y >= 0 && y < bh) px[y * bw + col] = color; +} + +static void px_text(uint32_t* px, int bw, int bh, + int x, int y, const char* text, Color c, int size) { + if (g_font) + g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size); +} +``` + +### Rounded Rectangles + +```cpp +static void px_fill_rounded(uint32_t* px, int bw, int bh, + int x, int y, int w, int h, int r, uint32_t color) { + for (int row = y; row < y + h && row < bh; row++) { + for (int col = x; col < x + w && col < bw; col++) { + int dx = 0, dy = 0; + if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; } + else if (col >= x+w-r && row < y + r) { dx = col - (x+w-r-1); dy = y + r - row; } + else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row - (y+h-r-1); } + else if (col >= x+w-r && row >= y+h-r) { dx = col - (x+w-r-1); dy = row - (y+h-r-1); } + if (dx * dx + dy * dy <= r * r) + px[row * bw + col] = color; + else if (dx == 0 && dy == 0) + px[row * bw + col] = color; + } + } +} +``` + +--- + +## Desktop-Integrated Apps + +Desktop apps are compiled into the desktop binary itself. They register callback functions that the compositor calls during its event loop. + +### Creating a Desktop App + +**Step 1: Define your app state** + +```cpp +// In apps/app_myapp.cpp +struct MyAppState { + int counter; + char label[64]; +}; +``` + +**Step 2: Implement callbacks** + +```cpp +static void myapp_on_draw(Window* win, Framebuffer& fb) { + MyAppState* state = (MyAppState*)win->app_data; + Canvas c(win); + + c.fill(colors::WINDOW_BG); + + // Draw toolbar + c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5)); + c.hline(0, 36, win->content_w, colors::BORDER); + + // Draw content + c.text(20, 60, state->label, colors::TEXT_COLOR); +} + +static void myapp_on_mouse(Window* win, MouseEvent& ev) { + MyAppState* state = (MyAppState*)win->app_data; + if (ev.left_pressed()) { + state->counter++; + win->dirty = true; // Request redraw + } +} + +static void myapp_on_key(Window* win, const Montauk::KeyEvent& key) { + if (!key.pressed) return; + MyAppState* state = (MyAppState*)win->app_data; + // Handle keystrokes... + win->dirty = true; +} + +static void myapp_on_close(Window* win) { + MyAppState* state = (MyAppState*)win->app_data; + montauk::mfree(state); +} +``` + +**Step 3: Write the open function** + +```cpp +void open_myapp(DesktopState* ds) { + int idx = desktop_create_window(ds, "My App", 400, 300, 320, 400); + if (idx < 0) return; + Window* win = &ds->windows[idx]; + + MyAppState* state = (MyAppState*)montauk::malloc(sizeof(MyAppState)); + montauk::memset(state, 0, sizeof(MyAppState)); + + win->app_data = state; + win->on_draw = myapp_on_draw; + win->on_mouse = myapp_on_mouse; + win->on_key = myapp_on_key; + win->on_close = myapp_on_close; + win->dirty = true; +} +``` + +**Step 4: Register in the app menu** + +Add an entry in `desktop_init()` (`main.cpp`) to the app menu so users can launch it. Include the `open_myapp` function in `apps_common.hpp` or similar. + +### Callback Reference + +| Callback | Signature | When Called | +|---|---|---| +| `on_draw` | `void(Window*, Framebuffer&)` | Every frame when `win->dirty` is true | +| `on_mouse` | `void(Window*, MouseEvent&)` | Mouse event within window content area | +| `on_key` | `void(Window*, const KeyEvent&)` | Keyboard event while window is focused | +| `on_close` | `void(Window*)` | Window close button clicked | +| `on_poll` | `void(Window*)` | Every frame, for background processing | + +### The `dirty` Flag + +Desktop apps use a `dirty` flag to control redraws. Set `win->dirty = true` after any state change that requires a visual update. The compositor skips `on_draw` for non-dirty windows. + +--- + +## Drawing and Rendering + +### Canvas API (Desktop Apps) + +The `Canvas` wraps a window's pixel buffer with drawing primitives: + +```cpp +Canvas c(win); // Construct from Window* + +// Fills +c.fill(Color c); // Entire buffer +c.fill_rect(int x, int y, int w, int h, Color c); // Rectangle +c.fill_rounded_rect(int x, int y, int w, int h, int r, Color c); // Rounded rect + +// Lines +c.hline(int x, int y, int len, Color c); // Horizontal +c.vline(int x, int y, int len, Color c); // Vertical +c.rect(int x, int y, int w, int h, Color c); // Outline + +// Text +c.text(int x, int y, const char* str, Color c); // TrueType or bitmap +c.text_2x(int x, int y, const char* str, Color c); // 2x scaled bitmap +c.text_mono(int x, int y, const char* str, Color c); // Monospace + +// UI elements +c.button(int x, int y, int w, int h, const char* label, + Color bg, Color fg, int radius); // Styled button +c.icon(int x, int y, const SvgIcon& ic); // SVG icon + +// Layout helpers +c.kv_line(int x, int* y, const char* line, Color c, int line_h); // Key-value line +c.separator(int x_start, int x_end, int* y, Color c, int spacing); // Horizontal separator +``` + +### Framebuffer API (Low-Level) + +For direct framebuffer access (used by the compositor itself and fullscreen apps): + +```cpp +Framebuffer fb; +fb.put_pixel(x, y, color); +fb.put_pixel_alpha(x, y, color); // With alpha blending +fb.fill_rect(x, y, w, h, color); +fb.fill_rect_alpha(x, y, w, h, color); +fb.blit(x, y, w, h, pixels); // Copy pixel region +fb.blit_alpha(x, y, w, h, pixels); // With alpha blending +fb.clear(color); +fb.flip(); // Swap to hardware +``` + +### Drawing Primitives + +From `gui/draw.hpp`, available for both Framebuffer-based rendering: + +```cpp +draw_hline(fb, x, y, w, color); +draw_vline(fb, x, y, h, color); +draw_rect(fb, x, y, w, h, color); +fill_rounded_rect(fb, x, y, w, h, radius, color); +fill_circle(fb, cx, cy, r, color); +draw_circle(fb, cx, cy, r, color); +draw_line(fb, x0, y0, x1, y1, color); // Bresenham's +draw_shadow(fb, x, y, w, h, offset, color); +``` + +--- + +## Text and Fonts + +### TrueType Fonts (Preferred) + +MontaukOS uses `stb_truetype` for font rendering. Fonts are loaded from the VFS: + +```cpp +TrueTypeFont* font = new TrueTypeFont(); +font->init("0:/fonts/Roboto-Medium.ttf"); + +// Render text to a pixel buffer +font->draw_to_buffer(pixels, buf_w, buf_h, x, y, "Hello", color, 18); + +// Measure text width before drawing +int width = font->measure_text("Hello", 18); + +// Get line height for layout +int line_h = font->get_line_height(18); +``` + +### System Fonts + +The desktop initializes a set of global fonts: + +```cpp +fonts::init(); // Call once at startup + +// Available fonts +fonts::system_font // Roboto-Medium.ttf (UI text) +fonts::system_bold // Roboto-Bold.ttf (headings) +fonts::mono // JetBrainsMono-Regular.ttf (code/terminal) +fonts::mono_bold // JetBrainsMono-Bold.ttf + +// Standard sizes +fonts::UI_SIZE // 18 (body text) +fonts::TITLE_SIZE // 18 (window titles) +fonts::LARGE_SIZE // 28 (headings) +fonts::TERM_SIZE // 18 (terminal) +``` + +### Glyph Caching + +TrueType fonts cache rasterized glyphs per pixel size. Up to 4 size caches are maintained per font. Access the cache directly for advanced metrics: + +```cpp +GlyphCache* cache = font->get_cache(18); +// cache->ascent, cache->descent — for line-height calculation +``` + +### Bitmap Font (Fallback) + +An 8x8 bitmap font is always available for basic text rendering when TrueType is not loaded: + +```cpp +draw_char(fb, x, y, 'A', color); +draw_text(fb, x, y, "Hello", color); +int w = text_width("Hello"); +``` + +--- + +## Input Handling + +### Keyboard + +```cpp +// In standalone apps (via win_poll) +if (ev.type == 0) { + Montauk::KeyEvent& key = ev.key; + if (!key.pressed) { /* key release */ } + + if (key.ascii >= 0x20 && key.ascii < 0x7F) { + // Printable character + } + + // Special keys by scancode + switch (key.scancode) { + case 0x01: /* Escape */ break; + case 0x0E: /* Backspace */ break; + case 0x1C: /* Enter */ break; + case 0x0F: /* Tab */ break; + case 0x53: /* Delete */ break; + case 0x48: /* Up */ break; + case 0x50: /* Down */ break; + case 0x4B: /* Left */ break; + case 0x4D: /* Right */ break; + case 0x47: /* Home */ break; + case 0x4F: /* End */ break; + case 0x49: /* Page Up */ break; + case 0x51: /* Page Down */ break; + } + + // Modifiers + if (key.ctrl) { /* Ctrl held */ } + if (key.shift) { /* Shift held */ } + if (key.alt) { /* Alt held */ } +} +``` + +### Mouse + +```cpp +// In standalone apps (via win_poll) +if (ev.type == 1) { + int mx = ev.mouse.x; + int my = ev.mouse.y; + + // Button state + bool left_down = ev.mouse.buttons & 0x01; + bool right_down = ev.mouse.buttons & 0x02; + + // Detect clicks (press edge) + bool left_pressed = (ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01); + bool left_released = !(ev.mouse.buttons & 0x01) && (ev.mouse.prev_buttons & 0x01); + + // Scroll wheel + int scroll = ev.mouse.scroll; // Positive = up, negative = down +} +``` + +In desktop apps, the `MouseEvent` struct provides convenience methods: + +```cpp +void myapp_on_mouse(Window* win, MouseEvent& ev) { + if (ev.left_pressed()) { /* click start */ } + if (ev.left_released()) { /* click end */ } + if (ev.left_held()) { /* dragging */ } + if (ev.right_pressed()) { /* context menu */ } + if (ev.scroll != 0) { /* scroll */ } +} +``` + +### Hit Testing + +A common pattern for clickable UI regions: + +```cpp +struct ButtonRect { int x, y, w, h; }; + +bool hit_test(ButtonRect& btn, int mx, int my) { + return mx >= btn.x && mx < btn.x + btn.w && + my >= btn.y && my < btn.y + btn.h; +} +``` + +--- + +## Widgets + +MontaukOS provides built-in widget types in `gui/widgets.hpp`: + +### Button + +```cpp +Button btn; +btn.init(x, y, width, height, "Click Me"); +btn.bg = colors::ACCENT; +btn.fg = colors::WHITE; +btn.on_click = [](void* data) { /* handle click */ }; +btn.userdata = my_state; + +// In draw callback +btn.draw(fb); + +// In mouse callback +btn.handle_mouse(ev); +``` + +### TextBox + +```cpp +TextBox tb; +tb.init(x, y, width, height); + +// In draw callback +tb.draw(fb); + +// In mouse callback (sets focus) +tb.handle_mouse(ev); + +// In key callback (text input) +tb.handle_key(key); + +// Read value +const char* value = tb.text; +``` + +### Scrollbar + +```cpp +Scrollbar sb; +sb.init(x, y, width, height); +sb.content_height = 2000; // Total content height +sb.view_height = 400; // Visible area height + +// In draw callback +sb.draw(fb); + +// In mouse callback +sb.handle_mouse(ev); + +// Use scroll_offset for content positioning +int offset = sb.scroll_offset; +``` + +--- + +## Colors and Theming + +### Color Construction + +```cpp +Color c1 = Color::from_rgb(0xFF, 0x00, 0x00); // Red +Color c2 = Color::from_rgba(0x00, 0x00, 0xFF, 0x80); // Semi-transparent blue +Color c3 = Color::from_hex(0x367BF0); // From hex +uint32_t pixel = c3.to_pixel(); // ARGB for pixel buffer +``` + +### System Colors + +Defined in `gui/gui.hpp` under the `colors` namespace: + +| Constant | Hex | Usage | +|---|---|---| +| `WINDOW_BG` | `#FFFFFF` | Window content background | +| `TEXT_COLOR` | `#333333` | Primary text | +| `ACCENT` | `#367BF0` | Links, selections, active elements | +| `BORDER` | `#D0D0D0` | Window/widget borders | +| `PANEL_BG` | `#2B3E50` | Taskbar/panel background | +| `PANEL_TEXT` | `#FFFFFF` | Panel text | +| `TITLEBAR_BG` | `#F5F5F5` | Window titlebar | +| `DESKTOP_BG` | `#E0E0E0` | Desktop background | +| `CLOSE_BTN` | `#FF5F57` | Close button (red) | +| `MAX_BTN` | `#28CA42` | Maximize button (green) | +| `MIN_BTN` | `#FFBD2E` | Minimize button (yellow) | +| `TERM_BG` | `#2D2D2D` | Terminal background | +| `TERM_FG` | `#CCCCCC` | Terminal text | +| `SCROLLBAR_BG` | | Scrollbar track | +| `SCROLLBAR_FG` | | Scrollbar thumb | + +### Toolbar Convention + +Standard toolbar pattern used across desktop apps: + +```cpp +// 36px tall, light gray background, thin bottom border +c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5)); +c.hline(0, 36, win->content_w, colors::BORDER); + +// 24x24 icon buttons centered at y=6 +c.icon(8, 6, my_icon); + +// Content starts below toolbar +int content_y = 37; +``` + +--- + +## Memory Management + +### Userspace Heap + +Use `montauk::malloc`, `montauk::mfree`, and `montauk::realloc` for dynamic allocation: + +```cpp +#include + +MyState* state = (MyState*)montauk::malloc(sizeof(MyState)); +montauk::memset(state, 0, sizeof(MyState)); +// ... use state ... +montauk::mfree(state); + +// Resize +char* buf = (char*)montauk::malloc(256); +buf = (char*)montauk::realloc(buf, 512); +``` + +The allocator uses size-class buckets (32 to 4096 bytes) with an overflow list for larger allocations. + +### Kernel Page Allocation + +`montauk::alloc` / `montauk::free` allocate kernel pages. Avoid for temporary buffers; use the heap instead. + +### Important Notes + +- **User stack is 32 KiB** (8 pages). Deep call chains (e.g., TrueType rendering) can approach this limit. Avoid large stack allocations. +- Use `inline` (not `static`) for shared globals in headers to avoid per-translation-unit copies and heap corruption. +- The libc needs `-fno-tree-loop-distribute-patterns` in CFLAGS to prevent GCC from converting `memcpy`/`memset` into calls to themselves. + +--- + +## Networking and HTTPS + +MontaukOS provides a shared TLS library (`tls/tls.hpp`) backed by BearSSL, and the MontaukAI dev environment adds a higher-level HTTP wrapper (`http/http.hpp`) on top. Build with `USE_TLS=1` to link TLS support. + +### HTTP Wrapper (`http/http.hpp`) + +Header-only library that handles DNS resolution, request building, TLS, response parsing, and cleanup. All functions return an `http::Response` struct. + +#### Setup + +```cpp +#include + +// Load CA certificates once at startup (required for HTTPS) +tls::TrustAnchors tas = tls::load_trust_anchors(); +``` + +#### GET + +```cpp +auto resp = http::get("api.example.com", "/v1/data", tas); +if (resp.status == 200) { + // resp.body is a pointer to the response body + // resp.body_len is its length +} +http::free_response(&resp); +``` + +#### POST + +```cpp +const char* json = "{\"name\":\"MontaukOS\",\"version\":1}"; +auto resp = http::post("api.example.com", "/v1/submit", + "application/json", + json, montauk::slen(json), + tas); +if (resp.status == 201) { + // Created successfully +} +http::free_response(&resp); +``` + +#### Other Methods (PUT, PATCH, DELETE, ...) + +```cpp +auto resp = http::request("PUT", "api.example.com", "/v1/item/42", + "application/json", + body, bodyLen, tas); +http::free_response(&resp); + +// DELETE with no body +auto resp2 = http::request("DELETE", "api.example.com", "/v1/item/42", + nullptr, nullptr, 0, tas); +http::free_response(&resp2); +``` + +#### Plain HTTP (No TLS, Port 80) + +```cpp +auto resp = http::get_plain("example.com", "/"); +if (resp.status == 200) { + // resp.body ... +} +http::free_response(&resp); +``` + +#### Reading Response Headers + +```cpp +char content_type[128]; +if (http::get_header(&resp, "Content-Type", content_type, sizeof(content_type))) { + // content_type is e.g. "application/json; charset=utf-8" +} +``` + +#### Custom Headers + +Pass extra headers as a string with `\r\n` terminators: + +```cpp +auto resp = http::get("api.example.com", "/v1/data", tas, + 32768, // response buffer size + "Authorization: Bearer tok_abc123\r\n" + "Accept: application/json\r\n"); +http::free_response(&resp); +``` + +#### Cancellable Requests + +For GUI apps that need to stay responsive during network I/O: + +```cpp +static bool g_quit = false; +static bool check_abort() { return g_quit; } + +auto resp = http::get("api.example.com", "/v1/slow", tas, + 32768, nullptr, check_abort); +http::free_response(&resp); +``` + +Set `g_quit = true` from your keyboard handler (e.g., on Escape) to cancel mid-request. + +#### Response Struct Reference + +```cpp +struct http::Response { + int status; // HTTP status code (200, 404, ...) or -1 on error + const char* headers; // Pointer to header block (within raw buffer) + int headers_len; + const char* body; // Pointer to body (within raw buffer) + int body_len; + char* raw; // Owned buffer — freed by free_response() + int raw_len; +}; +``` + +#### Function Signatures + +```cpp +// HTTPS GET +http::Response http::get(const char* host, const char* path, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr); + +// HTTPS POST +http::Response http::post(const char* host, const char* path, + const char* content_type, + const char* body, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr); + +// HTTPS with any method +http::Response http::request(const char* method, + const char* host, const char* path, + const char* content_type, + const char* body, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr); + +// Plain HTTP GET (port 80, no TLS) +http::Response http::get_plain(const char* host, const char* path, + int resp_buf_size = 32768, + const char* extra_headers = nullptr); + +// Parse raw HTTP response buffer (used internally, available if needed) +int http::parse_response(char* buf, int len, http::Response* out); + +// Case-insensitive header lookup +bool http::get_header(const http::Response* resp, const char* name, + char* out_val, int max_len); + +// Free the response's raw buffer +void http::free_response(http::Response* resp); +``` + +### Low-Level TLS API (`tls/tls.hpp`) + +If you need more control than `http::` provides (e.g., streaming responses, custom BearSSL setup), use the TLS layer directly: + +```cpp +#include + +tls::TrustAnchors tas = tls::load_trust_anchors(); + +// Build raw HTTP request yourself +char req[512]; +// ... "GET /stream HTTP/1.1\r\nHost: ...\r\n\r\n" ... + +char buf[65536]; +int n = tls::https_fetch("example.com", ip, 443, req, reqLen, tas, buf, sizeof(buf)); +``` + +See `syscalls.md` for the full `tls::` API reference. + +### Plain TCP/UDP + +For non-TLS networking without the HTTP wrapper, use the raw socket syscalls directly (see `syscalls.md`): + +```cpp +int sock = montauk::socket(Montauk::SOCK_TCP); // or SOCK_UDP +montauk::connect(sock, ip, port); +montauk::send(sock, data, len); +int n = montauk::recv(sock, buf, maxLen); +montauk::closesocket(sock); +``` + +--- + +## App Manifests + +External standalone apps can be discovered by the desktop through TOML manifest files placed in `0:/apps/`: + +```toml +[app] +name = "My App" +binary = "myapp" +icon = "myapp_icon.svg" + +[menu] +category = "Applications" +visible = true +``` + +**Categories:** `Applications`, `Internet`, `System`, `Games` + +The desktop scans `0:/apps/` at startup and adds matching entries to the application menu. The `binary` field is the executable name (looked up in the system path). + +--- + +## Build System + +### Independent Development (MontaukAI) + +The `MontaukAI/` directory provides a self-contained build environment. Edit the top of `Makefile` to configure your app: + +```makefile +APP_NAME := myapp +SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp src/network.cpp +``` + +Build with optional feature flags: + +```bash +make # GUI-only app +make USE_TLS=1 # With HTTPS/TLS (links libtls + libbearssl) +make USE_JPEG=1 # With JPEG decoding (links libjpeg) +make USE_TLS=1 USE_JPEG=1 # Both +make install # Copy ELF to MontaukOS ramdisk +``` + +The sysroot contains all headers and pre-built libraries: + +``` +sysroot/ +├── include/ +│ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h +│ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ... +│ ├── tls/ tls.hpp (HTTPS/TLS) +│ ├── Api/ Syscall.hpp (low-level syscall numbers) +│ ├── libc/ stdio.h, stdlib.h, string.h, ... (freestanding libc) +│ ├── bearssl*.h BearSSL headers (for USE_TLS=1) +│ └── (freestanding C/C++ standard headers) +└── lib/ + ├── liblibc.a C library (always linked) + ├── libtls.a TLS helper library + ├── libbearssl.a BearSSL crypto + └── libjpeg.a JPEG decoding (stb_image) +``` + +Key build details: +- **Toolchain:** `x86_64-elf-g++` cross-compiler (falls back to system g++) +- **Standard:** C++20 (`-std=gnu++20`), freestanding, no exceptions/RTTI +- **SSE:** Enabled (`-msse -msse2`) for floating-point / TrueType rendering +- **Entry point:** `extern "C" void _start()` (not `main`) +- **Load address:** `0x400000` (set in `link.ld`) +- **Runtime support:** `src/cxxrt.cpp` provides `operator new/delete` via `montauk::malloc/mfree` +- **TrueType support:** `src/stb_truetype_impl.cpp` provides the stb_truetype implementation + +### In-Tree Development + +Standalone apps can also live in `MontaukOS/programs/src//` with their own `Makefile`. Each app's Makefile sets `SRCS`, `CXXFLAGS`, `LDFLAGS`, and links against libraries in `programs/lib/`. + +Desktop-integrated apps are compiled as part of the desktop binary — add your `.cpp` file to the desktop's source list in `programs/src/desktop/Makefile`. diff --git a/template/docs/syscalls.md b/template/docs/syscalls.md new file mode 100644 index 0000000..576274e --- /dev/null +++ b/template/docs/syscalls.md @@ -0,0 +1,572 @@ +# MontaukOS Syscall Reference + +All syscalls are available through `#include ` in the `montauk` namespace. The syscall layer provides `syscall0()` through `syscall6()` primitives using AMD64 calling conventions. All raw syscalls return `int64_t`. + +## Table of Contents + +- [Process Management](#process-management) +- [File System](#file-system) +- [Memory](#memory) +- [Console I/O](#console-io) +- [Keyboard and Mouse](#keyboard-and-mouse) +- [Window Server](#window-server) +- [Framebuffer](#framebuffer) +- [Networking](#networking) +- [Audio](#audio) +- [Bluetooth](#bluetooth) +- [Timekeeping](#timekeeping) +- [System Information](#system-information) +- [Storage and Disks](#storage-and-disks) +- [Terminal](#terminal) +- [Process I/O Redirection](#process-io-redirection) +- [Configuration](#configuration) +- [User Management](#user-management) +- [Utility Libraries](#utility-libraries) + +--- + +## Process Management + +```cpp +void exit(int code); // Terminate process (noreturn) +void yield(); // Yield CPU to scheduler +void sleep_ms(uint64_t ms); // Sleep for milliseconds +int getpid(); // Get current process ID +int spawn(const char* path, const char* args); // Spawn child process (-1 on error) +int waitpid(int pid); // Wait for process to exit +int kill(int pid); // Kill a process +int proclist(ProcInfo* buf, int max); // List all processes (returns count) +``` + +**`ProcInfo` struct:** +```cpp +struct ProcInfo { + int pid; + char name[32]; + // ... additional fields +}; +``` + +### Arguments + +```cpp +int getargs(char* buf, uint64_t maxLen); // Get command-line arguments passed to this process +``` + +--- + +## File System + +```cpp +int open(const char* path); // Open file (returns fd, negative on error) +int close(int handle); // Close file handle +int read(int handle, uint8_t* buf, uint64_t off, uint64_t size); // Read bytes at offset (returns bytes read) +int fwrite(int handle, const uint8_t* buf, uint64_t off, uint64_t size); // Write bytes at offset +uint64_t getsize(int handle); // Get file size +int readdir(const char* path, const char** names, int max); // List directory entries (returns count) +int fcreate(const char* path); // Create file (returns fd) +int fdelete(const char* path); // Delete file (0 on success) +int fmkdir(const char* path); // Create directory +int drivelist(int* outDrives, int max); // Enumerate mounted drives (returns count) +``` + +### Path Format + +Paths use the format `:/`, e.g. `0:/fonts/Roboto-Medium.ttf`. Drive 0 is the boot drive (ramdisk). + +### Example: Reading a File + +```cpp +int fd = montauk::open("0:/config/settings.toml"); +if (fd < 0) { /* error */ } + +uint64_t size = montauk::getsize(fd); +uint8_t* buf = (uint8_t*)montauk::malloc(size + 1); +montauk::read(fd, buf, 0, size); +buf[size] = 0; // null-terminate +montauk::close(fd); + +// ... use buf ... +montauk::mfree(buf); +``` + +--- + +## Memory + +```cpp +void* alloc(uint64_t size); // Allocate kernel pages (avoid for temp buffers) +void free(void* ptr); // Free kernel pages +``` + +For general-purpose allocation, prefer the userspace heap (`montauk/heap.h`): + +```cpp +void* malloc(uint64_t size); +void mfree(void* ptr); +void* realloc(void* ptr, uint64_t size); +``` + +--- + +## Console I/O + +```cpp +void print(const char* text); // Write string to kernel console +void putchar(char c); // Write single character +``` + +These write to the kernel's text-mode console, not to a GUI window. + +--- + +## Keyboard and Mouse + +### Keyboard (Direct, Non-Windowed) + +```cpp +bool is_key_available(); // Poll for pending keystroke +void getkey(Montauk::KeyEvent* out); // Get next keystroke (blocks) +char getchar(); // Get single ASCII character (blocks) +``` + +**`KeyEvent` struct:** +```cpp +struct KeyEvent { + bool pressed; // true = key down, false = key up + uint8_t scancode; // PS/2 scancode + char ascii; // ASCII value (0 if non-printable) + bool shift, ctrl, alt; +}; +``` + +**Common Scancodes:** + +| Scancode | Key | +|---|---| +| `0x01` | Escape | +| `0x0E` | Backspace | +| `0x0F` | Tab | +| `0x1C` | Enter | +| `0x39` | Space | +| `0x53` | Delete | +| `0x48` | Up | +| `0x50` | Down | +| `0x4B` | Left | +| `0x4D` | Right | +| `0x47` | Home | +| `0x4F` | End | +| `0x49` | Page Up | +| `0x51` | Page Down | + +### Mouse (Direct, Non-Windowed) + +```cpp +void mouse_state(Montauk::MouseState* out); // Get current mouse state +void set_mouse_bounds(int32_t maxX, int32_t maxY); // Set mouse boundary +``` + +**`MouseState` struct:** +```cpp +struct MouseState { + int32_t x, y; + uint8_t buttons; // 0x01=Left, 0x02=Right, 0x04=Middle +}; +``` + +For GUI apps, prefer the windowed event system (`win_poll`) over direct mouse/keyboard syscalls. + +--- + +## Window Server + +These syscalls are for standalone GUI apps that run as separate processes. The desktop compositor manages window frames; your app renders into a shared pixel buffer. + +```cpp +int win_create(const char* title, int w, int h, WinCreateResult* result); +void win_destroy(int id); +uint64_t win_present(int id); // Mark window dirty, present to screen +int win_poll(int id, WinEvent* event); // Poll events (0=none, 1=event, <0=closed) +uint64_t win_resize(int id, int w, int h); // Resize, returns new pixel buffer address +uint64_t win_map(int id); // Get pixel buffer address +int win_enumerate(WinInfo* info, int max); // List all windows +int win_sendevent(int id, const WinEvent* event); // Send event to a window +int win_setscale(int scale); // Set UI scale factor +int win_getscale(); // Get UI scale factor +int win_setcursor(int id, int cursor); // Set cursor style +``` + +**`WinCreateResult` struct:** +```cpp +struct WinCreateResult { + int id; // Window ID for subsequent calls + uint64_t pixelVa; // Virtual address of shared pixel buffer (uint32_t* ARGB) +}; +``` + +**`WinEvent` struct:** +```cpp +struct WinEvent { + int type; // 0=Key, 1=Mouse, 2=Resize, 3=Close + union { + struct { uint8_t scancode; char ascii; bool pressed, shift, ctrl, alt; } key; + struct { int x, y; uint8_t buttons, prev_buttons; int32_t scroll; } mouse; + struct { int w, h; } resize; + }; +}; +``` + +### Event Loop Pattern + +```cpp +while (true) { + Montauk::WinEvent ev; + int r = montauk::win_poll(win_id, &ev); + if (r < 0) break; // Window closed + if (r == 0) { + montauk::sleep_ms(16); // No events, idle at ~60fps + continue; + } + switch (ev.type) { + case 0: handle_key(ev.key); break; + case 1: handle_mouse(ev.mouse); break; + case 2: handle_resize(ev.resize); break; + case 3: goto done; // Close + } + render(pixels); + montauk::win_present(win_id); +} +done: +montauk::win_destroy(win_id); +``` + +--- + +## Framebuffer + +For direct framebuffer access (fullscreen apps, not typical for windowed apps): + +```cpp +void fb_info(FbInfo* info); // Get dimensions and pitch +void* fb_map(); // Map framebuffer to user address space +``` + +**`FbInfo` struct:** +```cpp +struct FbInfo { + uint32_t width, height; + uint32_t pitch; // Bytes per row +}; +``` + +--- + +## Networking + +### DNS and Connectivity + +```cpp +int32_t ping(uint32_t ip, uint32_t timeoutMs); // Ping, returns RTT in ms (-1 on timeout) +uint32_t resolve(const char* hostname); // DNS lookup, returns IPv4 (0 on failure) +void get_netcfg(NetCfg* out); // Get network config +int set_netcfg(const NetCfg* cfg); // Set network config +``` + +### Sockets + +```cpp +int socket(int type); // Create socket (0=TCP, 1=UDP) +int connect(int fd, uint32_t ip, uint16_t port); // TCP connect +int bind(int fd, uint16_t port); // Bind to port +int listen(int fd); // Start listening +int accept(int fd); // Accept connection (returns new fd) +int send(int fd, const void* data, uint32_t len); // Send data (returns bytes sent) +int recv(int fd, void* buf, uint32_t maxLen); // Receive data (returns bytes read) +int closesocket(int fd); // Close socket +``` + +### UDP + +```cpp +int sendto(int fd, const void* data, uint32_t len, + uint32_t destIp, uint16_t destPort); +int recvfrom(int fd, void* buf, uint32_t maxLen, + uint32_t* srcIp, uint16_t* srcPort); +``` + +### Example: Plain HTTP GET (Port 80) + +```cpp +uint32_t ip = montauk::resolve("example.com"); +int sock = montauk::socket(0); // TCP +montauk::connect(sock, ip, 80); + +const char* req = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n"; +montauk::send(sock, req, montauk::slen(req)); + +char buf[4096]; +int n = montauk::recv(sock, buf, sizeof(buf) - 1); +buf[n] = 0; + +montauk::closesocket(sock); +``` + +### TLS / HTTPS Library + +Header: `tls/tls.hpp` — requires linking `libtls.a` and `libbearssl.a` (build with `USE_TLS=1`). + +Provides a high-level `tls::https_fetch()` that handles socket creation, BearSSL TLS 1.2 setup, handshake, request/response exchange, and cleanup in a single call. + +```cpp +#include + +// Load CA certificates (from 0:/etc/ca-certificates.crt) +tls::TrustAnchors tas = tls::load_trust_anchors(); + +// Build HTTP request +const char* host = "en.wikipedia.org"; +uint32_t ip = montauk::resolve(host); + +char req[256]; +// ... build "GET /path HTTP/1.1\r\nHost: ...\r\n\r\n" into req ... +int reqLen = montauk::slen(req); + +// Fetch (handles TLS handshake, send, receive, teardown) +char resp[32768]; +int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, resp, sizeof(resp)); +if (n > 0) { + resp[n] = 0; + // ... parse HTTP response ... +} +``` + +**API reference:** + +```cpp +namespace tls { + // Load PEM CA bundle from 0:/etc/ca-certificates.crt + TrustAnchors load_trust_anchors(); + + // High-level: DNS → socket → TLS → exchange → cleanup + int https_fetch(const char* host, uint32_t ip, uint16_t port, + const char* request, int reqLen, + const TrustAnchors& tas, + char* respBuf, int respMax, + AbortCheckFn abort_check = nullptr); + + // Lower-level: run TLS exchange on an existing socket + BearSSL engine + int tls_exchange(int fd, br_ssl_engine_context* eng, + const char* request, int reqLen, + char* respBuf, int respMax, + AbortCheckFn abort_check = nullptr); + + // Helpers for manual BearSSL usage + int tls_send_all(int fd, const unsigned char* data, size_t len); + int tls_recv_some(int fd, unsigned char* buf, size_t maxlen); + void get_bearssl_time(uint32_t* days, uint32_t* seconds); +} +``` + +The optional `AbortCheckFn` callback (e.g., `bool check_quit()`) lets terminal/GUI apps cancel a fetch in progress (return `true` to abort). + +### HTTP Wrapper (`http/http.hpp`) + +The MontaukAI dev environment includes a higher-level HTTP wrapper built on top of `tls::https_fetch()`. It handles DNS, request building, TLS, and response parsing automatically. See the "Networking and HTTPS" section in `gui-apps.md` for full documentation and examples. + +```cpp +#include + +tls::TrustAnchors tas = tls::load_trust_anchors(); + +auto resp = http::get("api.example.com", "/v1/data", tas); +if (resp.status == 200) { /* resp.body, resp.body_len */ } +http::free_response(&resp); + +auto resp2 = http::post("api.example.com", "/v1/submit", + "application/json", json, jsonLen, tas); +http::free_response(&resp2); +``` + +--- + +## Audio + +```cpp +int audio_open(uint32_t sampleRate, uint8_t channels, uint8_t bitsPerSample); +int audio_close(int handle); +int audio_write(int handle, const void* data, uint32_t size); // Write PCM samples +int audio_ctl(int handle, int cmd, int value); // Generic control +``` + +### Convenience Wrappers + +```cpp +int audio_set_volume(int handle, int percent); // 0-100 +int audio_get_volume(int handle); +int audio_pause(int handle); +int audio_resume(int handle); +int audio_get_pos(int handle); // Playback position +int audio_get_output(int handle); // Current output device +int audio_bt_status(int handle); // Bluetooth audio status +``` + +--- + +## Bluetooth + +```cpp +int bt_scan(BtScanResult* buf, int maxCount, uint32_t timeoutMs); // Scan for devices +int bt_connect(const uint8_t* bdAddr); // Connect +int bt_disconnect(const uint8_t* bdAddr); // Disconnect +int bt_list(BtDevInfo* buf, int maxCount); // List connected devices +int bt_info(BtAdapterInfo* buf); // Adapter info +``` + +--- + +## Timekeeping + +```cpp +uint64_t get_ticks(); // CPU tick counter +uint64_t get_milliseconds(); // Milliseconds since boot +void gettime(Montauk::DateTime* out); // Wall-clock time +``` + +**`DateTime` struct:** +```cpp +struct DateTime { + uint16_t year; + uint8_t month, day, hour, minute, second; + uint8_t weekday; +}; +``` + +--- + +## System Information + +```cpp +void get_info(SysInfo* info); // CPU, memory, system info +void memstats(MemStats* out); // Memory usage statistics +int64_t getrandom(void* buf, uint32_t len); // Cryptographic random bytes +void reset(); // System reset (noreturn) +void shutdown(); // System shutdown (noreturn) +``` + +--- + +## Storage and Disks + +```cpp +int partlist(PartInfo* buf, int max); // List GPT partitions +int disk_read(int blockDev, uint64_t lba, uint32_t sectorCount, void* buf); // Raw sector read +int disk_write(int blockDev, uint64_t lba, uint32_t sectorCount, const void* buf); // Raw sector write +int gpt_init(int blockDev); // Initialize GPT +int gpt_add(const GptAddParams* params); // Add partition +int fs_mount(int partIndex, int driveNum); // Mount filesystem +int fs_format(const FsFormatParams* params); // Format filesystem +int diskinfo(DiskInfo* buf, int port); // Get disk info +int devlist(DevInfo* buf, int max); // List block devices +``` + +--- + +## Terminal + +For terminal-mode (non-GUI) applications: + +```cpp +void termsize(int* cols, int* rows); // Get terminal dimensions +void termscale(int scale_x, int scale_y); // Set text scaling +void get_termscale(int* scale_x, int* scale_y); // Get text scaling +``` + +--- + +## Process I/O Redirection + +For launching child processes with redirected I/O (used by the terminal emulator): + +```cpp +int spawn_redir(const char* path, const char* args); // Spawn with I/O pipes +int childio_read(int childPid, char* buf, int maxLen); // Read child stdout +int childio_write(int childPid, const char* data, int len); // Write to child stdin +int childio_writekey(int childPid, const Montauk::KeyEvent* key); // Send keystroke to child +int childio_settermsz(int childPid, int cols, int rows); // Set child terminal size +``` + +--- + +## Configuration + +Header: `montauk/config.h` + +TOML-based configuration stored in `0:/config/`. Provides per-system and per-user config files. + +```cpp +toml::Doc config::load(const char* name); // Load 0:/config/.toml +int config::save(const char* name, toml::Doc* doc); // Save config (0 = success) +toml::Doc config::load_user(const char* username, const char* name); // Per-user config +int config::save_user(const char* username, const char* name, toml::Doc* doc); + +void config::set_string(toml::Doc* doc, const char* key, const char* val); +void config::set_int(toml::Doc* doc, const char* key, int64_t val); +void config::set_bool(toml::Doc* doc, const char* key, bool val); +bool config::unset(toml::Doc* doc, const char* key); +``` + +### Example + +```cpp +auto doc = montauk::config::load("session"); +const char* user = doc.get_string("session.username", "guest"); + +montauk::config::set_string(&doc, "session.theme", "dark"); +montauk::config::save("session", &doc); +``` + +--- + +## User Management + +Header: `montauk/user.h` + +User authentication and session management with SHA-256 password hashing. + +```cpp +bool user::authenticate(const char* username, const char* password); +bool user::create_user(const char* username, const char* display_name, + const char* password, const char* role); +bool user::delete_user(const char* username); +bool user::change_password(const char* username, const char* new_password); + +void user::set_session(const char* username); // Log in +void user::clear_session(); // Log out +bool user::get_session_username(char* buf, int sz); // Get current user +bool user::get_home_dir(char* buf, int sz); // Get user's home directory +``` + +--- + +## Utility Libraries + +### String Functions (`montauk/string.h`) + +```cpp +int slen(const char* s); +bool streq(const char* a, const char* b); +bool starts_with(const char* str, const char* prefix); +void memcpy(void* dst, const void* src, uint64_t n); +void memmove(void* dst, const void* src, uint64_t n); +void memset(void* dst, int val, uint64_t n); +void strcpy(char* dst, const char* src); +void strncpy(char* dst, const char* src, int max); +``` + +### Heap (`montauk/heap.h`) + +```cpp +void* malloc(uint64_t size); +void mfree(void* ptr); +void* realloc(void* ptr, uint64_t size); +``` diff --git a/template/link.ld b/template/link.ld new file mode 100644 index 0000000..6612f42 --- /dev/null +++ b/template/link.ld @@ -0,0 +1,43 @@ +/* + * link.ld + * Linker script for MontaukOS userspace programs + * Copyright (c) 2025 Daniel Hammer + * + * Programs are loaded at a standard user-space address. +*/ + +OUTPUT_FORMAT(elf64-x86-64) + +ENTRY(_start) + +SECTIONS +{ + . = 0x400000; + + .text : { + *(.text .text.*) + } + + . = ALIGN(4096); + + .rodata : { + *(.rodata .rodata.*) + } + + . = ALIGN(4096); + + .data : { + *(.data .data.*) + } + + .bss : { + *(.bss .bss.*) + *(COMMON) + } + + /DISCARD/ : { + *(.eh_frame*) + *(.note .note.*) + *(.comment*) + } +} diff --git a/template/src/cxxrt.cpp b/template/src/cxxrt.cpp new file mode 100644 index 0000000..f994507 --- /dev/null +++ b/template/src/cxxrt.cpp @@ -0,0 +1,15 @@ +/* + * cxxrt.cpp + * Minimal C++ runtime support for freestanding MontaukOS apps. + * Provides operator new/delete backed by montauk::malloc/mfree. + */ + +#include +#include + +void* operator new(size_t size) { return montauk::malloc(size); } +void* operator new[](size_t size) { return montauk::malloc(size); } +void operator delete(void* ptr) noexcept { montauk::mfree(ptr); } +void operator delete[](void* ptr) noexcept { montauk::mfree(ptr); } +void operator delete(void* ptr, size_t) noexcept { montauk::mfree(ptr); } +void operator delete[](void* ptr, size_t) noexcept { montauk::mfree(ptr); } diff --git a/template/src/main.cpp b/template/src/main.cpp new file mode 100644 index 0000000..8a48978 --- /dev/null +++ b/template/src/main.cpp @@ -0,0 +1,180 @@ +/* + * main.cpp + * Template standalone GUI app for MontaukOS + * + * This is a minimal working app that creates a window, renders text, + * and handles input events. Use it as a starting point for your app. + */ + +#include +#include +#include +#include +#include + +using namespace gui; + +// ============================================================================ +// State +// ============================================================================ + +static TrueTypeFont* g_font; +static int g_win_w = 500; +static int g_win_h = 400; +static int g_click_count = 0; + +// ============================================================================ +// Drawing helpers +// ============================================================================ + +static void px_fill(uint32_t* px, int bw, int bh, + int x, int y, int w, int h, uint32_t color) { + for (int row = y; row < y + h && row < bh; row++) + for (int col = x; col < x + w && col < bw; col++) + if (row >= 0 && col >= 0) + px[row * bw + col] = color; +} + +static void px_fill_rounded(uint32_t* px, int bw, int bh, + int x, int y, int w, int h, int r, uint32_t color) { + for (int row = y; row < y + h && row < bh; row++) { + for (int col = x; col < x + w && col < bw; col++) { + if (row < 0 || col < 0) continue; + int dx = 0, dy = 0; + if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; } + else if (col >= x+w-r && row < y + r) { dx = col-(x+w-r-1); dy = y + r - row; } + else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row-(y+h-r-1); } + else if (col >= x+w-r && row >= y+h-r) { dx = col-(x+w-r-1); dy = row-(y+h-r-1); } + if (dx * dx + dy * dy <= r * r) + px[row * bw + col] = color; + else if (dx == 0 && dy == 0) + px[row * bw + col] = color; + } + } +} + +static void px_text(uint32_t* px, int bw, int bh, + int x, int y, const char* text, Color c, int size) { + if (g_font) + g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size); +} + +static void px_hline(uint32_t* px, int bw, int bh, + int x, int y, int w, uint32_t color) { + if (y < 0 || y >= bh) return; + for (int col = x; col < x + w && col < bw; col++) + if (col >= 0) px[y * bw + col] = color; +} + +// ============================================================================ +// Rendering +// ============================================================================ + +static void render(uint32_t* pixels) { + // Background + px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, g_win_h, + Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel()); + + // Toolbar + px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, 36, + Color::from_rgb(0xF5, 0xF5, 0xF5).to_pixel()); + px_hline(pixels, g_win_w, g_win_h, 0, 36, g_win_w, + Color::from_rgb(0xD0, 0xD0, 0xD0).to_pixel()); + + // Title in toolbar + px_text(pixels, g_win_w, g_win_h, 12, 10, "My App", + Color::from_rgb(0x33, 0x33, 0x33), 18); + + // Content area + px_text(pixels, g_win_w, g_win_h, 20, 60, "Hello from MontaukOS!", + Color::from_rgb(0x33, 0x33, 0x33), 18); + + // Click counter + char buf[64]; + const char* prefix = "Clicks: "; + int i = 0; + while (prefix[i]) { buf[i] = prefix[i]; i++; } + int n = g_click_count; + if (n == 0) { buf[i++] = '0'; } + else { + char tmp[16]; int ti = 0; + while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; } + for (int j = ti - 1; j >= 0; j--) buf[i++] = tmp[j]; + } + buf[i] = 0; + + px_text(pixels, g_win_w, g_win_h, 20, 90, buf, + Color::from_rgb(0x66, 0x66, 0x66), 16); + + // A styled button + px_fill_rounded(pixels, g_win_w, g_win_h, + 20, 130, 120, 36, 4, + Color::from_rgb(0x36, 0x7B, 0xF0).to_pixel()); + px_text(pixels, g_win_w, g_win_h, 42, 139, "Click me", + Color::from_rgb(0xFF, 0xFF, 0xFF), 16); +} + +// ============================================================================ +// Entry point +// ============================================================================ + +extern "C" void _start() { + // Load font + g_font = new TrueTypeFont(); + if (!g_font->init("0:/fonts/Roboto-Medium.ttf")) + g_font = nullptr; + + // Create window + Montauk::WinCreateResult wres; + montauk::win_create("My App", g_win_w, g_win_h, &wres); + int win_id = wres.id; + uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa; + + // Initial render + render(pixels); + montauk::win_present(win_id); + + // Event loop + while (true) { + Montauk::WinEvent ev; + int r = montauk::win_poll(win_id, &ev); + + if (r < 0) break; + if (r == 0) { + montauk::sleep_ms(16); + continue; + } + + switch (ev.type) { + case 0: // Keyboard + if (ev.key.pressed && ev.key.scancode == 0x01) + goto done; // ESC to close + break; + + case 1: // Mouse + if ((ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01)) { + // Left click — check if inside button + int mx = ev.mouse.x, my = ev.mouse.y; + if (mx >= 20 && mx < 140 && my >= 130 && my < 166) + g_click_count++; + } + break; + + case 2: // Resize + g_win_w = ev.resize.w; + g_win_h = ev.resize.h; + pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h); + break; + + case 3: // Close + goto done; + } + + render(pixels); + montauk::win_present(win_id); + } + +done: + montauk::win_destroy(win_id); + montauk::exit(0); +} diff --git a/template/src/stb_truetype_impl.cpp b/template/src/stb_truetype_impl.cpp new file mode 100644 index 0000000..80309db --- /dev/null +++ b/template/src/stb_truetype_impl.cpp @@ -0,0 +1,32 @@ +/* + * stb_truetype_impl.cpp + * Single compilation unit for stb_truetype in MontaukOS freestanding environment + */ + +#include +#include +#include +#include +#include + +#define STBTT_ifloor(x) ((int) stb_floor(x)) +#define STBTT_iceil(x) ((int) stb_ceil(x)) +#define STBTT_sqrt(x) stb_sqrt(x) +#define STBTT_pow(x,y) stb_pow(x,y) +#define STBTT_fmod(x,y) stb_fmod(x,y) +#define STBTT_cos(x) stb_cos(x) +#define STBTT_acos(x) stb_acos(x) +#define STBTT_fabs(x) stb_fabs(x) + +#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x)) +#define STBTT_free(x,u) ((void)(u), montauk::mfree(x)) + +#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n) +#define STBTT_memset(d,v,n) montauk::memset(d,v,n) + +#define STBTT_strlen(x) montauk::slen(x) + +#define STBTT_assert(x) ((void)(x)) + +#define STB_TRUETYPE_IMPLEMENTATION +#include diff --git a/template/sysroot/include/Api/Syscall.hpp b/template/sysroot/include/Api/Syscall.hpp new file mode 100644 index 0000000..7dc1435 --- /dev/null +++ b/template/sysroot/include/Api/Syscall.hpp @@ -0,0 +1,318 @@ +/* + * Syscall.hpp + * MontaukOS syscall definitions for userspace programs + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include +#include + +namespace Montauk { + + // Syscall numbers + static constexpr uint64_t SYS_EXIT = 0; + static constexpr uint64_t SYS_YIELD = 1; + static constexpr uint64_t SYS_SLEEP_MS = 2; + static constexpr uint64_t SYS_GETPID = 3; + static constexpr uint64_t SYS_PRINT = 4; + static constexpr uint64_t SYS_PUTCHAR = 5; + static constexpr uint64_t SYS_OPEN = 6; + static constexpr uint64_t SYS_READ = 7; + static constexpr uint64_t SYS_GETSIZE = 8; + static constexpr uint64_t SYS_CLOSE = 9; + static constexpr uint64_t SYS_READDIR = 10; + static constexpr uint64_t SYS_ALLOC = 11; + static constexpr uint64_t SYS_FREE = 12; + static constexpr uint64_t SYS_GETTICKS = 13; + static constexpr uint64_t SYS_GETMILLISECONDS = 14; + static constexpr uint64_t SYS_GETINFO = 15; + static constexpr uint64_t SYS_ISKEYAVAILABLE = 16; + static constexpr uint64_t SYS_GETKEY = 17; + static constexpr uint64_t SYS_GETCHAR = 18; + static constexpr uint64_t SYS_PING = 19; + static constexpr uint64_t SYS_SPAWN = 20; + static constexpr uint64_t SYS_FBINFO = 21; + static constexpr uint64_t SYS_FBMAP = 22; + static constexpr uint64_t SYS_WAITPID = 23; + static constexpr uint64_t SYS_TERMSIZE = 24; + static constexpr uint64_t SYS_GETARGS = 25; + static constexpr uint64_t SYS_RESET = 26; + static constexpr uint64_t SYS_SHUTDOWN = 27; + static constexpr uint64_t SYS_GETTIME = 28; + static constexpr uint64_t SYS_SOCKET = 29; + static constexpr uint64_t SYS_CONNECT = 30; + static constexpr uint64_t SYS_BIND = 31; + static constexpr uint64_t SYS_LISTEN = 32; + static constexpr uint64_t SYS_ACCEPT = 33; + static constexpr uint64_t SYS_SEND = 34; + static constexpr uint64_t SYS_RECV = 35; + static constexpr uint64_t SYS_CLOSESOCK = 36; + static constexpr uint64_t SYS_GETNETCFG = 37; + static constexpr uint64_t SYS_SETNETCFG = 38; + static constexpr uint64_t SYS_SENDTO = 39; + static constexpr uint64_t SYS_RECVFROM = 40; + static constexpr uint64_t SYS_FWRITE = 41; + static constexpr uint64_t SYS_FCREATE = 42; + static constexpr uint64_t SYS_FDELETE = 77; + static constexpr uint64_t SYS_FMKDIR = 78; + static constexpr uint64_t SYS_DRIVELIST = 79; + static constexpr uint64_t SYS_TERMSCALE = 43; + static constexpr uint64_t SYS_RESOLVE = 44; + static constexpr uint64_t SYS_GETRANDOM = 45; + static constexpr uint64_t SYS_KLOG = 46; + static constexpr uint64_t SYS_MOUSESTATE = 47; + static constexpr uint64_t SYS_SETMOUSEBOUNDS = 48; + static constexpr uint64_t SYS_SPAWN_REDIR = 49; + static constexpr uint64_t SYS_CHILDIO_READ = 50; + static constexpr uint64_t SYS_CHILDIO_WRITE = 51; + static constexpr uint64_t SYS_CHILDIO_WRITEKEY = 52; + static constexpr uint64_t SYS_CHILDIO_SETTERMSZ = 53; + + // Window server syscalls + static constexpr uint64_t SYS_WINCREATE = 54; + static constexpr uint64_t SYS_WINDESTROY = 55; + static constexpr uint64_t SYS_WINPRESENT = 56; + static constexpr uint64_t SYS_WINPOLL = 57; + static constexpr uint64_t SYS_WINENUM = 58; + static constexpr uint64_t SYS_WINMAP = 59; + static constexpr uint64_t SYS_WINSENDEVENT = 60; + static constexpr uint64_t SYS_WINRESIZE = 64; + static constexpr uint64_t SYS_WINSETSCALE = 65; + static constexpr uint64_t SYS_WINGETSCALE = 66; + static constexpr uint64_t SYS_WINSETCURSOR = 68; + + // Process management syscalls + static constexpr uint64_t SYS_PROCLIST = 61; + static constexpr uint64_t SYS_KILL = 62; + static constexpr uint64_t SYS_DEVLIST = 63; + static constexpr uint64_t SYS_DISKINFO = 69; + + // Kernel introspection syscalls + static constexpr uint64_t SYS_MEMSTATS = 67; + + // Storage / partition syscalls + static constexpr uint64_t SYS_PARTLIST = 70; + static constexpr uint64_t SYS_DISKREAD = 71; + static constexpr uint64_t SYS_DISKWRITE = 72; + static constexpr uint64_t SYS_GPTINIT = 73; + static constexpr uint64_t SYS_GPTADD = 74; + static constexpr uint64_t SYS_FSMOUNT = 75; + static constexpr uint64_t SYS_FSFORMAT = 76; + + // Audio syscalls + static constexpr uint64_t SYS_AUDIOOPEN = 80; + static constexpr uint64_t SYS_AUDIOCLOSE = 81; + static constexpr uint64_t SYS_AUDIOWRITE = 82; + static constexpr uint64_t SYS_AUDIOCTL = 83; + + // Bluetooth syscalls + static constexpr uint64_t SYS_BTSCAN = 84; + static constexpr uint64_t SYS_BTCONNECT = 85; + static constexpr uint64_t SYS_BTDISCONNECT = 86; + static constexpr uint64_t SYS_BTLIST = 87; + static constexpr uint64_t SYS_BTINFO = 88; + + // Audio control commands (for SYS_AUDIOCTL) + static constexpr int AUDIO_CTL_SET_VOLUME = 0; + static constexpr int AUDIO_CTL_GET_VOLUME = 1; + static constexpr int AUDIO_CTL_GET_POS = 2; + static constexpr int AUDIO_CTL_PAUSE = 3; + static constexpr int AUDIO_CTL_GET_OUTPUT = 4; // 0=HDA, 1=Bluetooth + static constexpr int AUDIO_CTL_SET_OUTPUT = 5; // Switch audio output + static constexpr int AUDIO_CTL_BT_STATUS = 6; // Get Bluetooth connection status + + static constexpr int SOCK_TCP = 1; + static constexpr int SOCK_UDP = 2; + + struct NetCfg { + uint32_t ipAddress; // network byte order + uint32_t subnetMask; // network byte order + uint32_t gateway; // network byte order + uint8_t macAddress[6]; + uint8_t _pad[2]; + uint32_t dnsServer; // network byte order + }; + + struct DateTime { + uint16_t Year; + uint8_t Month; + uint8_t Day; + uint8_t Hour; + uint8_t Minute; + uint8_t Second; + }; + + struct FbInfo { + uint64_t width; + uint64_t height; + uint64_t pitch; // bytes per scanline + uint64_t bpp; // bits per pixel (32) + uint64_t userAddr; // filled by SYS_FBMAP (0 until mapped) + }; + + struct SysInfo { + char osName[32]; + char osVersion[32]; + uint32_t apiVersion; + uint32_t maxProcesses; + }; + + struct KeyEvent { + uint8_t scancode; + char ascii; + bool pressed; + bool shift; + bool ctrl; + bool alt; + }; + + struct MouseState { + int32_t x; + int32_t y; + int32_t scrollDelta; + uint8_t buttons; + }; + + // Window server shared types + struct WinEvent { + uint8_t type; // 0=key, 1=mouse, 2=resize, 3=close, 4=scale + uint8_t _pad[3]; + union { + KeyEvent key; + struct { int32_t x, y, scroll; uint8_t buttons, prev_buttons; } mouse; + struct { int32_t w, h; } resize; + struct { int32_t scale; } scale; + }; + }; + + struct WinInfo { + int32_t id; + int32_t ownerPid; + char title[64]; + int32_t width, height; + uint8_t dirty; + uint8_t cursor; // 0=arrow, 1=resize_h, 2=resize_v + uint8_t _pad2[2]; + }; + + struct WinCreateResult { + int32_t id; // -1 on failure + uint32_t _pad; + uint64_t pixelVa; // VA of pixel buffer in caller's address space + }; + + struct DevInfo { + uint8_t category; // 0=CPU, 1=Interrupt, 2=Timer, 3=Input, 4=USB, 5=Network, 6=Display, 7=Storage, 8=PCI + uint8_t _pad[3]; + char name[48]; + char detail[48]; + }; + + struct DiskInfo { + uint8_t port; // block device index + uint8_t type; // 0=none, 1=SATA, 2=SATAPI, 3=NVMe + uint8_t sataGen; // SATA gen (1/2/3) + uint8_t _pad0; + uint64_t sectorCount; // Total user-addressable sectors + uint16_t sectorSizeLog; // Logical sector size (bytes) + uint16_t sectorSizePhys; // Physical sector size (bytes) + uint16_t rpm; // 0=unknown, 1=SSD, else RPM + uint16_t ncqDepth; // 0 if no NCQ + uint8_t supportsLba48; + uint8_t supportsNcq; + uint8_t supportsTrim; + uint8_t supportsSmart; + uint8_t supportsWriteCache; + uint8_t supportsReadAhead; + uint8_t _pad1[2]; + char model[41]; + char serial[21]; + char firmware[9]; + char _pad2[1]; + }; + + struct PartGuid { + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; + }; + + struct PartInfo { + int32_t blockDev; // block device index + uint32_t _pad0; + uint64_t startLba; + uint64_t endLba; + uint64_t sectorCount; + PartGuid typeGuid; + PartGuid uniqueGuid; + uint64_t attributes; + char name[72]; // ASCII partition name + char typeName[24]; // human-readable type name + }; + + struct GptAddParams { + int32_t blockDev; + uint32_t _pad0; + uint64_t startLba; // 0 = auto (fill largest free region) + uint64_t endLba; // 0 = auto + PartGuid typeGuid; + char name[72]; + }; + + // Filesystem type IDs for SYS_FSFORMAT + static constexpr int FS_TYPE_FAT32 = 1; + static constexpr int FS_TYPE_EXT2 = 2; + + struct FsFormatParams { + int32_t partIndex; // global partition index + int32_t fsType; // FS_TYPE_FAT32, etc. + char label[32]; // volume label + }; + + // Bluetooth scan result (returned by SYS_BTSCAN) + struct BtScanResult { + uint8_t bdAddr[6]; + uint8_t _pad[2]; + uint32_t classOfDevice; + int8_t rssi; + uint8_t _pad2[3]; + char name[64]; + }; + + // Bluetooth connected device info (returned by SYS_BTLIST) + struct BtDevInfo { + uint8_t bdAddr[6]; + uint8_t connected; + uint8_t encrypted; + uint16_t handle; + uint8_t linkType; + uint8_t _pad; + }; + + // Bluetooth adapter info (returned by SYS_BTINFO) + struct BtAdapterInfo { + uint8_t bdAddr[6]; + uint8_t initialized; + uint8_t scanning; + char name[64]; + }; + + struct ProcInfo { + int32_t pid; + int32_t parentPid; + uint8_t state; // 0=Free, 1=Ready, 2=Running, 3=Terminated + uint8_t _pad[3]; + char name[64]; + uint64_t heapUsed; // heapNext - UserHeapBase (bytes) + }; + + struct MemStats { + uint64_t totalBytes; + uint64_t freeBytes; + uint64_t usedBytes; + uint64_t pageSize; + }; + +} diff --git a/template/sysroot/include/adxintrin.h b/template/sysroot/include/adxintrin.h new file mode 100644 index 0000000..c8e805b --- /dev/null +++ b/template/sysroot/include/adxintrin.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _ADXINTRIN_H_INCLUDED +#define _ADXINTRIN_H_INCLUDED + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_subborrow_u32 (unsigned char __CF, unsigned int __X, + unsigned int __Y, unsigned int *__P) +{ + return __builtin_ia32_sbb_u32 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarry_u32 (unsigned char __CF, unsigned int __X, + unsigned int __Y, unsigned int *__P) +{ + return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarryx_u32 (unsigned char __CF, unsigned int __X, + unsigned int __Y, unsigned int *__P) +{ + return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P); +} + +#ifdef __x86_64__ +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_subborrow_u64 (unsigned char __CF, unsigned long long __X, + unsigned long long __Y, unsigned long long *__P) +{ + return __builtin_ia32_sbb_u64 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarry_u64 (unsigned char __CF, unsigned long long __X, + unsigned long long __Y, unsigned long long *__P) +{ + return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarryx_u64 (unsigned char __CF, unsigned long long __X, + unsigned long long __Y, unsigned long long *__P) +{ + return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P); +} +#endif + +#endif /* _ADXINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/algorithm b/template/sysroot/include/algorithm new file mode 100644 index 0000000..a4602a8 --- /dev/null +++ b/template/sysroot/include/algorithm @@ -0,0 +1,94 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/algorithm + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ALGORITHM +#define _GLIBCXX_ALGORITHM 1 + +#pragma GCC system_header + +#include +#include +#if __cplusplus > 201703L +# include +#endif + +#define __glibcxx_want_clamp +#define __glibcxx_want_constexpr_algorithms +#define __glibcxx_want_freestanding_algorithm +#define __glibcxx_want_parallel_algorithm +#define __glibcxx_want_ranges_contains +#define __glibcxx_want_ranges_find_last +#define __glibcxx_want_ranges_fold +#define __glibcxx_want_robust_nonmodifying_seq_ops +#define __glibcxx_want_sample +#define __glibcxx_want_shift +#include + +#if __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED +// Parallel STL algorithms +# if _PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +# include +# else +// Otherwise just pull in forward declarations +# include +# define _PSTL_ALGORITHM_FORWARD_DECLARED 1 +# endif +#endif + +#ifdef _GLIBCXX_PARALLEL +# include +#endif + +#endif /* _GLIBCXX_ALGORITHM */ diff --git a/template/sysroot/include/ammintrin.h b/template/sysroot/include/ammintrin.h new file mode 100644 index 0000000..b94731a --- /dev/null +++ b/template/sysroot/include/ammintrin.h @@ -0,0 +1,93 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the AMD Programmers + Manual Update, version 2.x */ + +#ifndef _AMMINTRIN_H_INCLUDED +#define _AMMINTRIN_H_INCLUDED + +/* We need definitions from the SSE3, SSE2 and SSE header files*/ +#include + +#ifndef __SSE4A__ +#pragma GCC push_options +#pragma GCC target("sse4a") +#define __DISABLE_SSE4A__ +#endif /* __SSE4A__ */ + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_sd (double * __P, __m128d __Y) +{ + __builtin_ia32_movntsd (__P, (__v2df) __Y); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_ss (float * __P, __m128 __Y) +{ + __builtin_ia32_movntss (__P, (__v4sf) __Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_si64 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_extrq ((__v2di) __X, (__v16qi) __Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extracti_si64 (__m128i __X, unsigned const int __I, unsigned const int __L) +{ + return (__m128i) __builtin_ia32_extrqi ((__v2di) __X, __I, __L); +} +#else +#define _mm_extracti_si64(X, I, L) \ + ((__m128i) __builtin_ia32_extrqi ((__v2di)(__m128i)(X), \ + (unsigned int)(I), (unsigned int)(L))) +#endif + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_si64 (__m128i __X,__m128i __Y) +{ + return (__m128i) __builtin_ia32_insertq ((__v2di)__X, (__v2di)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_inserti_si64(__m128i __X, __m128i __Y, unsigned const int __I, unsigned const int __L) +{ + return (__m128i) __builtin_ia32_insertqi ((__v2di)__X, (__v2di)__Y, __I, __L); +} +#else +#define _mm_inserti_si64(X, Y, I, L) \ + ((__m128i) __builtin_ia32_insertqi ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), \ + (unsigned int)(I), (unsigned int)(L))) +#endif + +#ifdef __DISABLE_SSE4A__ +#undef __DISABLE_SSE4A__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE4A__ */ + +#endif /* _AMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/amxbf16intrin.h b/template/sysroot/include/amxbf16intrin.h new file mode 100644 index 0000000..57569cb --- /dev/null +++ b/template/sysroot/include/amxbf16intrin.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AMXBF16INTRIN_H_INCLUDED +#define _AMXBF16INTRIN_H_INCLUDED + +#if !defined(__AMX_BF16__) +#pragma GCC push_options +#pragma GCC target("amx-bf16") +#define __DISABLE_AMX_BF16__ +#endif /* __AMX_BF16__ */ + +#if defined(__x86_64__) +#define _tile_dpbf16ps_internal(dst,src1,src2) \ + __asm__ volatile\ + ("{tdpbf16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpbf16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::) + +#define _tile_dpbf16ps(dst,src1,src2) \ + _tile_dpbf16ps_internal (dst, src1, src2) + +#endif + +#ifdef __DISABLE_AMX_BF16__ +#undef __DISABLE_AMX_BF16__ +#pragma GCC pop_options +#endif /* __DISABLE_AMX_BF16__ */ + +#endif /* _AMXBF16INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/amxcomplexintrin.h b/template/sysroot/include/amxcomplexintrin.h new file mode 100644 index 0000000..92ac561 --- /dev/null +++ b/template/sysroot/include/amxcomplexintrin.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AMXCOMPLEXINTRIN_H_INCLUDED +#define _AMXCOMPLEXINTRIN_H_INCLUDED + +#if !defined(__AMX_COMPLEX__) +#pragma GCC push_options +#pragma GCC target("amx-complex") +#define __DISABLE_AMX_COMPLEX__ +#endif /* __AMX_COMPLEX__ */ + +#if defined(__x86_64__) +#define _tile_cmmimfp16ps_internal(src1_dst,src2,src3) \ + __asm__ volatile\ + ("{tcmmimfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmimfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::) + +#define _tile_cmmrlfp16ps_internal(src1_dst,src2,src3) \ + __asm__ volatile\ + ("{tcmmrlfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmrlfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::) + +#define _tile_cmmimfp16ps(src1_dst,src2,src3) \ + _tile_cmmimfp16ps_internal (src1_dst, src2, src3) + +#define _tile_cmmrlfp16ps(src1_dst,src2,src3) \ + _tile_cmmrlfp16ps_internal (src1_dst, src2, src3) + +#endif + +#ifdef __DISABLE_AMX_COMPLEX__ +#undef __DISABLE_AMX_COMPLEX__ +#pragma GCC pop_options +#endif /* __DISABLE_AMX_COMPLEX__ */ + +#endif /* _AMXCOMPLEXINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/amxfp16intrin.h b/template/sysroot/include/amxfp16intrin.h new file mode 100644 index 0000000..a46b272 --- /dev/null +++ b/template/sysroot/include/amxfp16intrin.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AMXFP16INTRIN_H_INCLUDED +#define _AMXFP16INTRIN_H_INCLUDED + +#if defined(__x86_64__) +#define _tile_dpfp16ps_internal(dst,src1,src2) \ + __asm__ volatile \ + ("{tdpfp16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpfp16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::) + +#define _tile_dpfp16ps(dst,src1,src2) \ + _tile_dpfp16ps_internal (dst,src1,src2) + +#endif + +#ifdef __DISABLE_AMX_FP16__ +#undef __DISABLE_AMX_FP16__ +#pragma GCC pop_options +#endif /* __DISABLE_AMX_FP16__ */ + +#endif /* _AMXFP16INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/amxint8intrin.h b/template/sysroot/include/amxint8intrin.h new file mode 100644 index 0000000..c65ad38 --- /dev/null +++ b/template/sysroot/include/amxint8intrin.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AMXINT8INTRIN_H_INCLUDED +#define _AMXINT8INTRIN_H_INCLUDED + +#if !defined(__AMX_INT8__) +#pragma GCC push_options +#pragma GCC target("amx-int8") +#define __DISABLE_AMX_INT8__ +#endif /* __AMX_INT8__ */ + +#if defined(__x86_64__) +#define _tile_int8_dp_internal(name,dst,src1,src2) \ + __asm__ volatile \ + ("{"#name"\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|"#name"\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::) + +#define _tile_dpbssd(dst,src1,src2) \ + _tile_int8_dp_internal (tdpbssd, dst, src1, src2) + +#define _tile_dpbsud(dst,src1,src2) \ + _tile_int8_dp_internal (tdpbsud, dst, src1, src2) + +#define _tile_dpbusd(dst,src1,src2) \ + _tile_int8_dp_internal (tdpbusd, dst, src1, src2) + +#define _tile_dpbuud(dst,src1,src2) \ + _tile_int8_dp_internal (tdpbuud, dst, src1, src2) + +#endif + +#ifdef __DISABLE_AMX_INT8__ +#undef __DISABLE_AMX_INT8__ +#pragma GCC pop_options +#endif /* __DISABLE_AMX_INT8__ */ + +#endif /* _AMXINT8INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/amxtileintrin.h b/template/sysroot/include/amxtileintrin.h new file mode 100644 index 0000000..5081b32 --- /dev/null +++ b/template/sysroot/include/amxtileintrin.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AMXTILEINTRIN_H_INCLUDED +#define _AMXTILEINTRIN_H_INCLUDED + +#if !defined(__AMX_TILE__) +#pragma GCC push_options +#pragma GCC target("amx-tile") +#define __DISABLE_AMX_TILE__ +#endif /* __AMX_TILE__ */ + +#if defined(__x86_64__) +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tile_loadconfig (const void *__config) +{ + __builtin_ia32_ldtilecfg (__config); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tile_storeconfig (void *__config) +{ + __builtin_ia32_sttilecfg (__config); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tile_release (void) +{ + __asm__ volatile ("tilerelease" ::); +} + +#define _tile_loadd(dst,base,stride) \ + _tile_loadd_internal (dst, base, stride) + +#define _tile_loadd_internal(dst,base,stride) \ + __asm__ volatile \ + ("{tileloadd\t(%0,%1,1), %%tmm"#dst"|tileloadd\t%%tmm"#dst", [%0+%1*1]}" \ + :: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride))) + +#define _tile_stream_loadd(dst,base,stride) \ + _tile_stream_loadd_internal (dst, base, stride) + +#define _tile_stream_loadd_internal(dst,base,stride) \ + __asm__ volatile \ + ("{tileloaddt1\t(%0,%1,1), %%tmm"#dst"|tileloaddt1\t%%tmm"#dst", [%0+%1*1]}" \ + :: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride))) + +#define _tile_stored(dst,base,stride) \ + _tile_stored_internal (dst, base, stride) + +#define _tile_stored_internal(src,base,stride) \ + __asm__ volatile \ + ("{tilestored\t%%tmm"#src", (%0,%1,1)|tilestored\t[%0+%1*1], %%tmm"#src"}" \ + :: "r" ((void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)) \ + : "memory") + +#define _tile_zero(dst) \ + _tile_zero_internal (dst) + +#define _tile_zero_internal(dst) \ + __asm__ volatile \ + ("tilezero\t%%tmm"#dst ::) + +#endif + +#ifdef __DISABLE_AMX_TILE__ +#undef __DISABLE_AMX_TILE__ +#pragma GCC pop_options +#endif /* __DISABLE_AMX_TILE__ */ + +#endif /* _AMXTILEINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/array b/template/sysroot/include/array new file mode 100644 index 0000000..8710bf7 --- /dev/null +++ b/template/sysroot/include/array @@ -0,0 +1,519 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/array + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ARRAY +#define _GLIBCXX_ARRAY 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +#include +#include +#include +#include // std::begin, std::end etc. +#include // std::index_sequence, std::tuple_size +#include + +#define __glibcxx_want_array_constexpr +#define __glibcxx_want_freestanding_array +#define __glibcxx_want_nonmember_container_access +#define __glibcxx_want_to_array +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + struct __array_traits + { + using _Type = _Tp[_Nm]; + using _Is_swappable = __is_swappable<_Tp>; + using _Is_nothrow_swappable = __is_nothrow_swappable<_Tp>; + }; + + template + struct __array_traits<_Tp, 0> + { + // Empty type used instead of _Tp[0] for std::array<_Tp, 0>. + struct _Type + { + // Indexing is undefined. + __attribute__((__always_inline__,__noreturn__)) + _Tp& operator[](size_t) const noexcept { __builtin_trap(); } + + // Conversion to a pointer produces a null pointer. + __attribute__((__always_inline__)) + constexpr explicit operator _Tp*() const noexcept { return nullptr; } + }; + + using _Is_swappable = true_type; + using _Is_nothrow_swappable = true_type; + }; + + /** + * @brief A standard container for storing a fixed size sequence of elements. + * + * @ingroup sequences + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence. + * + * Sets support random access iterators. + * + * @tparam Tp Type of element. Required to be a complete type. + * @tparam Nm Number of elements. + */ + template + struct array + { + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + // Support for zero-sized arrays mandatory. + typename __array_traits<_Tp, _Nm>::_Type _M_elems; + + // No explicit construct/copy/destroy for aggregate type. + + // DR 776. + _GLIBCXX20_CONSTEXPR void + fill(const value_type& __u) + { std::fill_n(begin(), size(), __u); } + + _GLIBCXX20_CONSTEXPR void + swap(array& __other) + noexcept(__array_traits<_Tp, _Nm>::_Is_nothrow_swappable::value) + { std::swap_ranges(begin(), end(), __other.begin()); } + + // Iterators. + [[__gnu__::__const__, __nodiscard__]] + _GLIBCXX17_CONSTEXPR iterator + begin() noexcept + { return iterator(data()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_iterator + begin() const noexcept + { return const_iterator(data()); } + + [[__gnu__::__const__, __nodiscard__]] + _GLIBCXX17_CONSTEXPR iterator + end() noexcept + { return iterator(data() + _Nm); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_iterator + end() const noexcept + { return const_iterator(data() + _Nm); } + + [[__gnu__::__const__, __nodiscard__]] + _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin() noexcept + { return reverse_iterator(end()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(end()); } + + [[__gnu__::__const__, __nodiscard__]] + _GLIBCXX17_CONSTEXPR reverse_iterator + rend() noexcept + { return reverse_iterator(begin()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(begin()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_iterator + cbegin() const noexcept + { return const_iterator(data()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_iterator + cend() const noexcept + { return const_iterator(data() + _Nm); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } + + // Capacity. + [[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]] + constexpr size_type + size() const noexcept { return _Nm; } + + [[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]] + constexpr size_type + max_size() const noexcept { return _Nm; } + + [[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]] + constexpr bool + empty() const noexcept { return size() == 0; } + + // Element access. + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR reference + operator[](size_type __n) noexcept + { + __glibcxx_requires_subscript(__n); + return _M_elems[__n]; + } + + [[__nodiscard__]] + constexpr const_reference + operator[](size_type __n) const noexcept + { +#if __cplusplus >= 201402L + __glibcxx_requires_subscript(__n); +#endif + return _M_elems[__n]; + } + + _GLIBCXX17_CONSTEXPR reference + at(size_type __n) + { + if (__n >= _Nm) + std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm); + return _M_elems[__n]; + } + + constexpr const_reference + at(size_type __n) const + { + // Result of conditional expression must be an lvalue so use + // boolean ? lvalue : (throw-expr, lvalue) + return __n < _Nm ? _M_elems[__n] + : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm), + _M_elems[__n]); + } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR reference + front() noexcept + { + __glibcxx_requires_nonempty(); + return _M_elems[(size_type)0]; + } + + [[__nodiscard__]] + constexpr const_reference + front() const noexcept + { +#if __cplusplus >= 201402L + __glibcxx_requires_nonempty(); +#endif + return _M_elems[(size_type)0]; + } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR reference + back() noexcept + { + __glibcxx_requires_nonempty(); + return _M_elems[_Nm - 1]; + } + + [[__nodiscard__]] + constexpr const_reference + back() const noexcept + { +#if __cplusplus >= 201402L + __glibcxx_requires_nonempty(); +#endif + return _M_elems[_Nm - 1]; + } + + [[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]] + _GLIBCXX17_CONSTEXPR pointer + data() noexcept + { return static_cast(_M_elems); } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR const_pointer + data() const noexcept + { return static_cast(_M_elems); } + }; + +#if __cpp_deduction_guides >= 201606 + template + array(_Tp, _Up...) + -> array && ...), _Tp>, + 1 + sizeof...(_Up)>; +#endif + + // Array comparisons. + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return std::equal(__one.begin(), __one.end(), __two.begin()); } + +#if __cpp_lib_three_way_comparison // C++ >= 20 && lib_concepts + template + [[nodiscard]] + constexpr __detail::__synth3way_t<_Tp> + operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { + if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) + if (!std::__is_constant_evaluated()) + { + constexpr size_t __n = _Nm * sizeof(_Tp); + return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; + } + + for (size_t __i = 0; __i < _Nm; ++__i) + { + auto __c = __detail::__synth3way(__a[__i], __b[__i]); + if (__c != 0) + return __c; + } + return strong_ordering::equal; + } +#else + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one == __two); } + + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { + return std::lexicographical_compare(__a.begin(), __a.end(), + __b.begin(), __b.end()); + } + + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return __two < __one; } + + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one > __two); } + + template + [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one < __two); } +#endif // three_way_comparison && concepts + + // Specialized algorithms. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + __enable_if_t<__array_traits<_Tp, _Nm>::_Is_swappable::value> +#else + void +#endif + swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) + noexcept(noexcept(__one.swap(__two))) + { __one.swap(__two); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + __enable_if_t::_Is_swappable::value> + swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; +#endif + + template + [[__nodiscard__]] + constexpr _Tp& + get(array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return __arr._M_elems[_Int]; + } + + template + [[__nodiscard__]] + constexpr _Tp&& + get(array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(std::get<_Int>(__arr)); + } + + template + [[__nodiscard__]] + constexpr const _Tp& + get(const array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return __arr._M_elems[_Int]; + } + + template + [[__nodiscard__]] + constexpr const _Tp&& + get(const array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(std::get<_Int>(__arr)); + } + +#ifdef __cpp_lib_to_array // C++ >= 20 && __cpp_generic_lambdas >= 201707L + template + [[nodiscard]] + constexpr array, _Nm> + to_array(_Tp (&__a)[_Nm]) + noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_constructible_v<_Tp, _Tp&>); + if constexpr (is_constructible_v<_Tp, _Tp&>) + { + if constexpr (is_trivially_copyable_v<_Tp> + && is_trivially_default_constructible_v<_Tp> + && is_copy_assignable_v<_Tp>) + { + array, _Nm> __arr; + if (!__is_constant_evaluated() && _Nm != 0) + __builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a)); + else + for (size_t __i = 0; __i < _Nm; ++__i) + __arr._M_elems[__i] = __a[__i]; + return __arr; + } + else + return [&__a](index_sequence<_Idx...>) { + return array, _Nm>{{ __a[_Idx]... }}; + }(make_index_sequence<_Nm>{}); + } + else + __builtin_unreachable(); // FIXME: see PR c++/91388 + } + + template + [[nodiscard]] + constexpr array, _Nm> + to_array(_Tp (&&__a)[_Nm]) + noexcept(is_nothrow_move_constructible_v<_Tp>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_move_constructible_v<_Tp>); + if constexpr (is_move_constructible_v<_Tp>) + { + if constexpr (is_trivially_copyable_v<_Tp> + && is_trivially_default_constructible_v<_Tp> + && is_copy_assignable_v<_Tp>) + { + array, _Nm> __arr; + if (!__is_constant_evaluated() && _Nm != 0) + __builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a)); + else + for (size_t __i = 0; __i < _Nm; ++__i) + __arr._M_elems[__i] = __a[__i]; + return __arr; + } + else + return [&__a](index_sequence<_Idx...>) { + return array, _Nm>{{ std::move(__a[_Idx])... }}; + }(make_index_sequence<_Nm>{}); + } + else + __builtin_unreachable(); // FIXME: see PR c++/91388 + } +#endif // __cpp_lib_to_array + + // Tuple interface to class template array. + + /// Partial specialization for std::array + template + struct tuple_size> + : public integral_constant { }; + + /// Partial specialization for std::array + template + struct tuple_element<_Ind, array<_Tp, _Nm>> + { + static_assert(_Ind < _Nm, "array index is in range"); + using type = _Tp; + }; + +#if __cplusplus >= 201703L + template + inline constexpr size_t tuple_size_v> = _Nm; + + template + inline constexpr size_t tuple_size_v> = _Nm; +#endif + + template + struct __is_tuple_like_impl> : true_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_ARRAY diff --git a/template/sysroot/include/atomic b/template/sysroot/include/atomic new file mode 100644 index 0000000..a75baf3 --- /dev/null +++ b/template/sysroot/include/atomic @@ -0,0 +1,1800 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/atomic + * This is a Standard C++ Library header. + */ + +// Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl. +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +#ifndef _GLIBCXX_ATOMIC +#define _GLIBCXX_ATOMIC 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#define __glibcxx_want_atomic_is_always_lock_free +#define __glibcxx_want_atomic_flag_test +#define __glibcxx_want_atomic_float +#define __glibcxx_want_atomic_ref +#define __glibcxx_want_atomic_lock_free_type_aliases +#define __glibcxx_want_atomic_value_initialization +#define __glibcxx_want_atomic_wait +#include + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup atomics + * @{ + */ + + template + struct atomic; + + /// atomic + // NB: No operators or fetch-operations for this type. + template<> + struct atomic + { + using value_type = bool; + + private: + __atomic_base _M_base; + + public: + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(bool __i) noexcept : _M_base(__i) { } + + bool + operator=(bool __i) noexcept + { return _M_base.operator=(__i); } + + bool + operator=(bool __i) volatile noexcept + { return _M_base.operator=(__i); } + + operator bool() const noexcept + { return _M_base.load(); } + + operator bool() const volatile noexcept + { return _M_base.load(); } + + bool + is_lock_free() const noexcept { return _M_base.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; +#endif + + void + store(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { _M_base.store(__i, __m); } + + void + store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { _M_base.store(__i, __m); } + + bool + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_base.load(__m); } + + bool + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_base.load(__m); } + + bool + exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.exchange(__i, __m); } + + bool + exchange(bool __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.exchange(__i, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + +#if __cpp_lib_atomic_wait + void + wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept + { _M_base.wait(__old, __m); } + + // TODO add const volatile overload + + void + notify_one() noexcept + { _M_base.notify_one(); } + + void + notify_all() noexcept + { _M_base.notify_all(); } +#endif // __cpp_lib_atomic_wait + }; + +/// @cond undocumented +#if __cpp_lib_atomic_value_initialization +# define _GLIBCXX20_INIT(I) = I +#else +# define _GLIBCXX20_INIT(I) +#endif +/// @endcond + + /** + * @brief Generic atomic type, primary class template. + * + * @tparam _Tp Type to be made atomic, must be trivially copyable. + */ + template + struct atomic + { + using value_type = _Tp; + + private: + // Align 1/2/4/8/16-byte types to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + static constexpr int _S_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp()); + + static_assert(__is_trivially_copyable(_Tp), + "std::atomic requires a trivially copyable type"); + + static_assert(sizeof(_Tp) > 0, + "Incomplete or zero-sized types are not supported"); + +#if __cplusplus > 201703L + static_assert(is_copy_constructible_v<_Tp>); + static_assert(is_move_constructible_v<_Tp>); + static_assert(is_copy_assignable_v<_Tp>); + static_assert(is_move_assignable_v<_Tp>); +#endif + + public: + atomic() = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(_Tp __i) noexcept : _M_i(__i) + { +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>()) + __builtin_clear_padding(std::__addressof(_M_i)); +#endif + } + + operator _Tp() const noexcept + { return load(); } + + operator _Tp() const volatile noexcept + { return load(); } + + _Tp + operator=(_Tp __i) noexcept + { store(__i); return __i; } + + _Tp + operator=(_Tp __i) volatile noexcept + { store(__i); return __i; } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_M_i), 0); +#endif + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { + __atomic_store(std::__addressof(_M_i), + __atomic_impl::__clear_padding(__i), + int(__m)); + } + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { + __atomic_store(std::__addressof(_M_i), + __atomic_impl::__clear_padding(__i), + int(__m)); + } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), + __atomic_impl::__clear_padding(__i), + __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), + __atomic_impl::__clear_padding(__i), + __ptr, int(__m)); + return *__ptr; + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_impl::__compare_exchange(_M_i, __e, __i, true, + __s, __f); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_impl::__compare_exchange(_M_i, __e, __i, true, + __s, __f); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_impl::__compare_exchange(_M_i, __e, __i, false, + __s, __f); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_impl::__compare_exchange(_M_i, __e, __i, false, + __s, __f); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + +#if __cpp_lib_atomic_wait // C++ >= 20 + void + wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept + { + std::__atomic_wait_address_v(&_M_i, __old, + [__m, this] { return this->load(__m); }); + } + + // TODO add const volatile overload + + void + notify_one() noexcept + { std::__atomic_notify_address(&_M_i, false); } + + void + notify_all() noexcept + { std::__atomic_notify_address(&_M_i, true); } +#endif // __cpp_lib_atomic_wait + + }; +#undef _GLIBCXX20_INIT + + /// Partial specialization for pointer types. + template + struct atomic<_Tp*> + { + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + typedef _Tp* __pointer_type; + typedef __atomic_base<_Tp*> __base_type; + __base_type _M_b; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { } + + operator __pointer_type() const noexcept + { return __pointer_type(_M_b); } + + operator __pointer_type() const volatile noexcept + { return __pointer_type(_M_b); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator++(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator++(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator--(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator--(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator++() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator++() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator--() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator--() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + bool + is_lock_free() const noexcept + { return _M_b.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept + { return _M_b.is_lock_free(); } + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free + = ATOMIC_POINTER_LOCK_FREE == 2; +#endif + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.store(__p, __m); } + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.store(__p, __m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_b.load(__m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_b.load(__m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.exchange(__p, __m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.exchange(__p, __m); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + +#if __cpp_lib_atomic_wait + void + wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) const noexcept + { _M_b.wait(__old, __m); } + + // TODO add const volatile overload + + void + notify_one() noexcept + { _M_b.notify_one(); } + + void + notify_all() noexcept + { _M_b.notify_all(); } +#endif // __cpp_lib_atomic_wait + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + }; + + + /// Explicit specialization for char. + template<> + struct atomic : __atomic_base + { + typedef char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for signed char. + template<> + struct atomic : __atomic_base + { + typedef signed char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned char. + template<> + struct atomic : __atomic_base + { + typedef unsigned char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for short. + template<> + struct atomic : __atomic_base + { + typedef short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned short. + template<> + struct atomic : __atomic_base + { + typedef unsigned short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for int. + template<> + struct atomic : __atomic_base + { + typedef int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned int. + template<> + struct atomic : __atomic_base + { + typedef unsigned int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long. + template<> + struct atomic : __atomic_base + { + typedef long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long long. + template<> + struct atomic : __atomic_base + { + typedef long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for wchar_t. + template<> + struct atomic : __atomic_base + { + typedef wchar_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; +#endif + }; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + template<> + struct atomic : __atomic_base + { + typedef char8_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free + = ATOMIC_CHAR8_T_LOCK_FREE == 2; +#endif + }; +#endif + + /// Explicit specialization for char16_t. + template<> + struct atomic : __atomic_base + { + typedef char16_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free + = ATOMIC_CHAR16_T_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for char32_t. + template<> + struct atomic : __atomic_base + { + typedef char32_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17 + static constexpr bool is_always_lock_free + = ATOMIC_CHAR32_T_LOCK_FREE == 2; +#endif + }; + + + /// atomic_bool + typedef atomic atomic_bool; + + /// atomic_char + typedef atomic atomic_char; + + /// atomic_schar + typedef atomic atomic_schar; + + /// atomic_uchar + typedef atomic atomic_uchar; + + /// atomic_short + typedef atomic atomic_short; + + /// atomic_ushort + typedef atomic atomic_ushort; + + /// atomic_int + typedef atomic atomic_int; + + /// atomic_uint + typedef atomic atomic_uint; + + /// atomic_long + typedef atomic atomic_long; + + /// atomic_ulong + typedef atomic atomic_ulong; + + /// atomic_llong + typedef atomic atomic_llong; + + /// atomic_ullong + typedef atomic atomic_ullong; + + /// atomic_wchar_t + typedef atomic atomic_wchar_t; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// atomic_char8_t + typedef atomic atomic_char8_t; +#endif + + /// atomic_char16_t + typedef atomic atomic_char16_t; + + /// atomic_char32_t + typedef atomic atomic_char32_t; + +#ifdef _GLIBCXX_USE_C99_STDINT + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2441. Exact-width atomic typedefs should be provided + + /// atomic_int8_t + typedef atomic atomic_int8_t; + + /// atomic_uint8_t + typedef atomic atomic_uint8_t; + + /// atomic_int16_t + typedef atomic atomic_int16_t; + + /// atomic_uint16_t + typedef atomic atomic_uint16_t; + + /// atomic_int32_t + typedef atomic atomic_int32_t; + + /// atomic_uint32_t + typedef atomic atomic_uint32_t; + + /// atomic_int64_t + typedef atomic atomic_int64_t; + + /// atomic_uint64_t + typedef atomic atomic_uint64_t; +#endif + + /// atomic_int_least8_t + typedef atomic atomic_int_least8_t; + + /// atomic_uint_least8_t + typedef atomic atomic_uint_least8_t; + + /// atomic_int_least16_t + typedef atomic atomic_int_least16_t; + + /// atomic_uint_least16_t + typedef atomic atomic_uint_least16_t; + + /// atomic_int_least32_t + typedef atomic atomic_int_least32_t; + + /// atomic_uint_least32_t + typedef atomic atomic_uint_least32_t; + + /// atomic_int_least64_t + typedef atomic atomic_int_least64_t; + + /// atomic_uint_least64_t + typedef atomic atomic_uint_least64_t; + + + /// atomic_int_fast8_t + typedef atomic atomic_int_fast8_t; + + /// atomic_uint_fast8_t + typedef atomic atomic_uint_fast8_t; + + /// atomic_int_fast16_t + typedef atomic atomic_int_fast16_t; + + /// atomic_uint_fast16_t + typedef atomic atomic_uint_fast16_t; + + /// atomic_int_fast32_t + typedef atomic atomic_int_fast32_t; + + /// atomic_uint_fast32_t + typedef atomic atomic_uint_fast32_t; + + /// atomic_int_fast64_t + typedef atomic atomic_int_fast64_t; + + /// atomic_uint_fast64_t + typedef atomic atomic_uint_fast64_t; + + + /// atomic_intptr_t + typedef atomic atomic_intptr_t; + + /// atomic_uintptr_t + typedef atomic atomic_uintptr_t; + + /// atomic_size_t + typedef atomic atomic_size_t; + + /// atomic_ptrdiff_t + typedef atomic atomic_ptrdiff_t; + + /// atomic_intmax_t + typedef atomic atomic_intmax_t; + + /// atomic_uintmax_t + typedef atomic atomic_uintmax_t; + + // Function definitions, atomic_flag operations. + inline bool + atomic_flag_test_and_set_explicit(atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + + inline bool + atomic_flag_test_and_set_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + +#if __cpp_lib_atomic_flag_test + inline bool + atomic_flag_test(const atomic_flag* __a) noexcept + { return __a->test(); } + + inline bool + atomic_flag_test(const volatile atomic_flag* __a) noexcept + { return __a->test(); } + + inline bool + atomic_flag_test_explicit(const atomic_flag* __a, + memory_order __m) noexcept + { return __a->test(__m); } + + inline bool + atomic_flag_test_explicit(const volatile atomic_flag* __a, + memory_order __m) noexcept + { return __a->test(__m); } +#endif + + inline void + atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept + { __a->clear(__m); } + + inline void + atomic_flag_clear_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { __a->clear(__m); } + + inline bool + atomic_flag_test_and_set(atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline bool + atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(volatile atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + +#if __cpp_lib_atomic_wait + inline void + atomic_flag_wait(atomic_flag* __a, bool __old) noexcept + { __a->wait(__old); } + + inline void + atomic_flag_wait_explicit(atomic_flag* __a, bool __old, + memory_order __m) noexcept + { __a->wait(__old, __m); } + + inline void + atomic_flag_notify_one(atomic_flag* __a) noexcept + { __a->notify_one(); } + + inline void + atomic_flag_notify_all(atomic_flag* __a) noexcept + { __a->notify_all(); } +#endif // __cpp_lib_atomic_wait + + /// @cond undocumented + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3220. P0558 broke conforming C++14 uses of atomic shared_ptr + template + using __atomic_val_t = __type_identity_t<_Tp>; + template + using __atomic_diff_t = typename atomic<_Tp>::difference_type; + /// @endcond + + // [atomics.nonmembers] Non-member functions. + // Function templates generally applicable to atomic types. + template + inline bool + atomic_is_lock_free(const atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline bool + atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline void + atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline void + atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline _ITp + atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_load_explicit(const volatile atomic<_ITp>* __a, + memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline _ITp + atomic_exchange_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline bool + atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + + template + inline void + atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline void + atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const volatile atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline bool + atomic_compare_exchange_weak(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + +#if __cpp_lib_atomic_wait + template + inline void + atomic_wait(const atomic<_Tp>* __a, + typename std::atomic<_Tp>::value_type __old) noexcept + { __a->wait(__old); } + + template + inline void + atomic_wait_explicit(const atomic<_Tp>* __a, + typename std::atomic<_Tp>::value_type __old, + std::memory_order __m) noexcept + { __a->wait(__old, __m); } + + template + inline void + atomic_notify_one(atomic<_Tp>* __a) noexcept + { __a->notify_one(); } + + template + inline void + atomic_notify_all(atomic<_Tp>* __a) noexcept + { __a->notify_all(); } +#endif // __cpp_lib_atomic_wait + + // Function templates for atomic_integral and atomic_pointer operations only. + // Some operations (and, or, xor) are only available for atomic integrals, + // which is implemented by taking a parameter of type __atomic_base<_ITp>*. + + template + inline _ITp + atomic_fetch_add_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_add(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_add(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + +#ifdef __cpp_lib_atomic_float + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(float __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + +#if !(defined(__clang__) && !__STDC_HOSTED__) // clang in kernel context + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(long double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; +#endif + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct atomic<_Float16> : __atomic_float<_Float16> + { + atomic() noexcept = default; + + constexpr + atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float<_Float16>::operator=; + }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct atomic<_Float32> : __atomic_float<_Float32> + { + atomic() noexcept = default; + + constexpr + atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float<_Float32>::operator=; + }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct atomic<_Float64> : __atomic_float<_Float64> + { + atomic() noexcept = default; + + constexpr + atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float<_Float64>::operator=; + }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct atomic<_Float128> : __atomic_float<_Float128> + { + atomic() noexcept = default; + + constexpr + atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float<_Float128>::operator=; + }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t> + { + atomic() noexcept = default; + + constexpr + atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=; + }; +#endif +#endif // __cpp_lib_atomic_float + +#ifdef __cpp_lib_atomic_ref + /// Class template to provide atomic operations on a non-atomic variable. + template + struct atomic_ref : __atomic_ref<_Tp> + { + explicit + atomic_ref(_Tp& __t) noexcept : __atomic_ref<_Tp>(__t) + { } + + atomic_ref& operator=(const atomic_ref&) = delete; + + atomic_ref(const atomic_ref&) = default; + + using __atomic_ref<_Tp>::operator=; + }; +#endif // __cpp_lib_atomic_ref + +#ifdef __cpp_lib_atomic_lock_free_type_aliases +# ifdef _GLIBCXX_HAVE_PLATFORM_WAIT + using atomic_signed_lock_free + = atomic>; + using atomic_unsigned_lock_free + = atomic>; +# elif ATOMIC_INT_LOCK_FREE == 2 + using atomic_signed_lock_free = atomic; + using atomic_unsigned_lock_free = atomic; +# elif ATOMIC_LONG_LOCK_FREE == 2 + using atomic_signed_lock_free = atomic; + using atomic_unsigned_lock_free = atomic; +# elif ATOMIC_CHAR_LOCK_FREE == 2 + using atomic_signed_lock_free = atomic; + using atomic_unsigned_lock_free = atomic; +# else +# error "libstdc++ bug: no lock-free atomics but they were emitted in " +# endif +#endif + + /// @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_ATOMIC diff --git a/template/sysroot/include/avx2intrin.h b/template/sysroot/include/avx2intrin.h new file mode 100644 index 0000000..cb0801e --- /dev/null +++ b/template/sysroot/include/avx2intrin.h @@ -0,0 +1,2270 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX2INTRIN_H_INCLUDED +#define _AVX2INTRIN_H_INCLUDED + +#ifndef __AVX2__ +#pragma GCC push_options +#pragma GCC target("avx2") +#define __DISABLE_AVX2__ +#endif /* __AVX2__ */ + +/* Sum absolute 8-bit integer difference of adjacent groups of 4 + byte integers in the first 2 operands. Starting offsets within + operands are determined by the 3rd mask operand. */ +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mpsadbw_epu8 (__m256i __X, __m256i __Y, const int __M) +{ + return (__m256i) __builtin_ia32_mpsadbw256 ((__v32qi)__X, + (__v32qi)__Y, __M); +} +#else +#define _mm256_mpsadbw_epu8(X, Y, M) \ + ((__m256i) __builtin_ia32_mpsadbw256 ((__v32qi)(__m256i)(X), \ + (__v32qi)(__m256i)(Y), (int)(M))) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_abs_epi8 (__m256i __A) +{ + return (__m256i)__builtin_ia32_pabsb256 ((__v32qi)__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_abs_epi16 (__m256i __A) +{ + return (__m256i)__builtin_ia32_pabsw256 ((__v16hi)__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_abs_epi32 (__m256i __A) +{ + return (__m256i)__builtin_ia32_pabsd256 ((__v8si)__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_packs_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_packssdw256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_packs_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_packsswb256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_packus_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_packusdw256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_packus_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_packuswb256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v32qu)__A + (__v32qu)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v16hu)__A + (__v16hu)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8su)__A + (__v8su)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A + (__v4du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_adds_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_paddsb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_adds_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_paddsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_adds_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_paddusb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_adds_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_paddusw256 ((__v16hi)__A, (__v16hi)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_alignr_epi8 (__m256i __A, __m256i __B, const int __N) +{ + return (__m256i) __builtin_ia32_palignr256 ((__v4di)__A, + (__v4di)__B, + __N * 8); +} +#else +/* In that case (__N*8) will be in vreg, and insn will not be matched. */ +/* Use define instead */ +#define _mm256_alignr_epi8(A, B, N) \ + ((__m256i) __builtin_ia32_palignr256 ((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), \ + (int)(N) * 8)) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_and_si256 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A & (__v4du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_andnot_si256 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_andnotsi256 ((__v4di)__A, (__v4di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avg_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pavgb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avg_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pavgw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blendv_epi8 (__m256i __X, __m256i __Y, __m256i __M) +{ + return (__m256i) __builtin_ia32_pblendvb256 ((__v32qi)__X, + (__v32qi)__Y, + (__v32qi)__M); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blend_epi16 (__m256i __X, __m256i __Y, const int __M) +{ + return (__m256i) __builtin_ia32_pblendw256 ((__v16hi)__X, + (__v16hi)__Y, + __M); +} +#else +#define _mm256_blend_epi16(X, Y, M) \ + ((__m256i) __builtin_ia32_pblendw256 ((__v16hi)(__m256i)(X), \ + (__v16hi)(__m256i)(Y), (int)(M))) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v32qi)__A == (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v16hi)__A == (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8si)__A == (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4di)__A == (__v4di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v32qs)__A > (__v32qs)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v16hi)__A > (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8si)__A > (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4di)__A > (__v4di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hadd_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phaddw256 ((__v16hi)__X, + (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hadd_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phaddd256 ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hadds_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phaddsw256 ((__v16hi)__X, + (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hsub_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phsubw256 ((__v16hi)__X, + (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hsub_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phsubd256 ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hsubs_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_phsubsw256 ((__v16hi)__X, + (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maddubs_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmaddubsw256 ((__v32qi)__X, + (__v32qi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_madd_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaddwd256 ((__v16hi)__A, + (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxsb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxsd256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxub256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxuw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epu32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxud256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminsb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminsd256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminub256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminuw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epu32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminud256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movemask_epi8 (__m256i __A) +{ + return __builtin_ia32_pmovmskb256 ((__v32qi)__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi8_epi16 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxbw256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi8_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxbd256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi8_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxbq256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi16_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxwd256 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi16_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxwq256 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxdq256 ((__v4si)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu8_epi16 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxbw256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu8_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxbd256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu8_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxbq256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu16_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxwd256 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu16_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxwq256 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu32_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxdq256 ((__v4si)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mul_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmuldq256 ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mulhrs_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmulhrsw256 ((__v16hi)__X, + (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mulhi_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmulhuw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mulhi_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmulhw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mullo_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v16hu)__A * (__v16hu)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mullo_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8su)__A * (__v8su)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mul_epu32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmuludq256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_or_si256 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A | (__v4du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sad_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_psadbw256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_epi8 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pshufb256 ((__v32qi)__X, + (__v32qi)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_epi32 (__m256i __A, const int __mask) +{ + return (__m256i)__builtin_ia32_pshufd256 ((__v8si)__A, __mask); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shufflehi_epi16 (__m256i __A, const int __mask) +{ + return (__m256i)__builtin_ia32_pshufhw256 ((__v16hi)__A, __mask); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shufflelo_epi16 (__m256i __A, const int __mask) +{ + return (__m256i)__builtin_ia32_pshuflw256 ((__v16hi)__A, __mask); +} +#else +#define _mm256_shuffle_epi32(A, N) \ + ((__m256i)__builtin_ia32_pshufd256 ((__v8si)(__m256i)(A), (int)(N))) +#define _mm256_shufflehi_epi16(A, N) \ + ((__m256i)__builtin_ia32_pshufhw256 ((__v16hi)(__m256i)(A), (int)(N))) +#define _mm256_shufflelo_epi16(A, N) \ + ((__m256i)__builtin_ia32_pshuflw256 ((__v16hi)(__m256i)(A), (int)(N))) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sign_epi8 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psignb256 ((__v32qi)__X, (__v32qi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sign_epi16 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psignw256 ((__v16hi)__X, (__v16hi)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sign_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psignd256 ((__v8si)__X, (__v8si)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bslli_epi128 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_pslldqi256 (__A, __N * 8); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_slli_si256 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_pslldqi256 (__A, __N * 8); +} +#else +#define _mm256_bslli_epi128(A, N) \ + ((__m256i)__builtin_ia32_pslldqi256 ((__m256i)(A), (int)(N) * 8)) +#define _mm256_slli_si256(A, N) \ + ((__m256i)__builtin_ia32_pslldqi256 ((__m256i)(A), (int)(N) * 8)) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_slli_epi16 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psllwi256 ((__v16hi)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sll_epi16 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psllw256((__v16hi)__A, (__v8hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_slli_epi32 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_pslldi256 ((__v8si)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sll_epi32 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_pslld256((__v8si)__A, (__v4si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_slli_epi64 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psllqi256 ((__v4di)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sll_epi64 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psllq256((__v4di)__A, (__v2di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srai_epi16 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psrawi256 ((__v16hi)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sra_epi16 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psraw256 ((__v16hi)__A, (__v8hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srai_epi32 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psradi256 ((__v8si)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sra_epi32 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psrad256 ((__v8si)__A, (__v4si)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bsrli_epi128 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_psrldqi256 (__A, __N * 8); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srli_si256 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_psrldqi256 (__A, __N * 8); +} +#else +#define _mm256_bsrli_epi128(A, N) \ + ((__m256i)__builtin_ia32_psrldqi256 ((__m256i)(A), (int)(N) * 8)) +#define _mm256_srli_si256(A, N) \ + ((__m256i)__builtin_ia32_psrldqi256 ((__m256i)(A), (int)(N) * 8)) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srli_epi16 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psrlwi256 ((__v16hi)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srl_epi16 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psrlw256((__v16hi)__A, (__v8hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srli_epi32 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psrldi256 ((__v8si)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srl_epi32 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psrld256((__v8si)__A, (__v4si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srli_epi64 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_psrlqi256 ((__v4di)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srl_epi64 (__m256i __A, __m128i __B) +{ + return (__m256i)__builtin_ia32_psrlq256((__v4di)__A, (__v2di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v32qu)__A - (__v32qu)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v16hu)__A - (__v16hu)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8su)__A - (__v8su)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A - (__v4du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_subs_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_psubsb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_subs_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_psubsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_subs_epu8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_psubusb256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_subs_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_psubusw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpckhbw256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpckhwd256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpckhdq256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpckhqdq256 ((__v4di)__A, (__v4di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpcklbw256 ((__v32qi)__A, (__v32qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpcklwd256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpckldq256 ((__v8si)__A, (__v8si)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_punpcklqdq256 ((__v4di)__A, (__v4di)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_xor_si256 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A ^ (__v4du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_stream_load_si256 (__m256i const *__X) +{ + return (__m256i) __builtin_ia32_movntdqa256 ((__v4di *) __X); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastss_ps (__m128 __X) +{ + return (__m128) __builtin_ia32_vbroadcastss_ps ((__v4sf)__X); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastss_ps (__m128 __X) +{ + return (__m256) __builtin_ia32_vbroadcastss_ps256 ((__v4sf)__X); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastsd_pd (__m128d __X) +{ + return (__m256d) __builtin_ia32_vbroadcastsd_pd256 ((__v2df)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastsi128_si256 (__m128i __X) +{ + return (__m256i) __builtin_ia32_vbroadcastsi256 ((__v2di)__X); +} + +#define _mm_broadcastsi128_si256(X) _mm256_broadcastsi128_si256(X) +#define _mm_broadcastsd_pd(X) _mm_movedup_pd(X) + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blend_epi32 (__m128i __X, __m128i __Y, const int __M) +{ + return (__m128i) __builtin_ia32_pblendd128 ((__v4si)__X, + (__v4si)__Y, + __M); +} +#else +#define _mm_blend_epi32(X, Y, M) \ + ((__m128i) __builtin_ia32_pblendd128 ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(M))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blend_epi32 (__m256i __X, __m256i __Y, const int __M) +{ + return (__m256i) __builtin_ia32_pblendd256 ((__v8si)__X, + (__v8si)__Y, + __M); +} +#else +#define _mm256_blend_epi32(X, Y, M) \ + ((__m256i) __builtin_ia32_pblendd256 ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(M))) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastb_epi8 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pbroadcastb256 ((__v16qi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastw_epi16 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pbroadcastw256 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastd_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pbroadcastd256 ((__v4si)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastq_epi64 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pbroadcastq256 ((__v2di)__X); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastb_epi8 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pbroadcastb128 ((__v16qi)__X); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastw_epi16 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pbroadcastw128 ((__v8hi)__X); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastd_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pbroadcastd128 ((__v4si)__X); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastq_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pbroadcastq128 ((__v2di)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutevar8x32_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvarsi256 ((__v8si)__X, (__v8si)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute4x64_pd (__m256d __X, const int __M) +{ + return (__m256d) __builtin_ia32_permdf256 ((__v4df)__X, __M); +} +#else +#define _mm256_permute4x64_pd(X, M) \ + ((__m256d) __builtin_ia32_permdf256 ((__v4df)(__m256d)(X), (int)(M))) +#endif + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutevar8x32_ps (__m256 __X, __m256i __Y) +{ + return (__m256) __builtin_ia32_permvarsf256 ((__v8sf)__X, (__v8si)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute4x64_epi64 (__m256i __X, const int __M) +{ + return (__m256i) __builtin_ia32_permdi256 ((__v4di)__X, __M); +} +#else +#define _mm256_permute4x64_epi64(X, M) \ + ((__m256i) __builtin_ia32_permdi256 ((__v4di)(__m256i)(X), (int)(M))) +#endif + + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2x128_si256 (__m256i __X, __m256i __Y, const int __M) +{ + return (__m256i) __builtin_ia32_permti256 ((__v4di)__X, (__v4di)__Y, __M); +} +#else +#define _mm256_permute2x128_si256(X, Y, M) \ + ((__m256i) __builtin_ia32_permti256 ((__v4di)(__m256i)(X), (__v4di)(__m256i)(Y), (int)(M))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extracti128_si256 (__m256i __X, const int __M) +{ + return (__m128i) __builtin_ia32_extract128i256 ((__v4di)__X, __M); +} +#else +#define _mm256_extracti128_si256(X, M) \ + ((__m128i) __builtin_ia32_extract128i256 ((__v4di)(__m256i)(X), (int)(M))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_inserti128_si256 (__m256i __X, __m128i __Y, const int __M) +{ + return (__m256i) __builtin_ia32_insert128i256 ((__v4di)__X, (__v2di)__Y, __M); +} +#else +#define _mm256_inserti128_si256(X, Y, M) \ + ((__m256i) __builtin_ia32_insert128i256 ((__v4di)(__m256i)(X), \ + (__v2di)(__m128i)(Y), \ + (int)(M))) +#endif + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskload_epi32 (int const *__X, __m256i __M ) +{ + return (__m256i) __builtin_ia32_maskloadd256 ((const __v8si *)__X, + (__v8si)__M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskload_epi64 (long long const *__X, __m256i __M ) +{ + return (__m256i) __builtin_ia32_maskloadq256 ((const __v4di *)__X, + (__v4di)__M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskload_epi32 (int const *__X, __m128i __M ) +{ + return (__m128i) __builtin_ia32_maskloadd ((const __v4si *)__X, + (__v4si)__M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskload_epi64 (long long const *__X, __m128i __M ) +{ + return (__m128i) __builtin_ia32_maskloadq ((const __v2di *)__X, + (__v2di)__M); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskstore_epi32 (int *__X, __m256i __M, __m256i __Y ) +{ + __builtin_ia32_maskstored256 ((__v8si *)__X, (__v8si)__M, (__v8si)__Y); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskstore_epi64 (long long *__X, __m256i __M, __m256i __Y ) +{ + __builtin_ia32_maskstoreq256 ((__v4di *)__X, (__v4di)__M, (__v4di)__Y); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskstore_epi32 (int *__X, __m128i __M, __m128i __Y ) +{ + __builtin_ia32_maskstored ((__v4si *)__X, (__v4si)__M, (__v4si)__Y); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskstore_epi64 (long long *__X, __m128i __M, __m128i __Y ) +{ + __builtin_ia32_maskstoreq (( __v2di *)__X, (__v2di)__M, (__v2di)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sllv_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv8si ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sllv_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv4si ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sllv_epi64 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv4di ((__v4di)__X, (__v4di)__Y); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sllv_epi64 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv2di ((__v2di)__X, (__v2di)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srav_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrav8si ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srav_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrav4si ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srlv_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv8si ((__v8si)__X, (__v8si)__Y); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srlv_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv4si ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srlv_epi64 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv4di ((__v4di)__X, (__v4di)__Y); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srlv_epi64 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv2di ((__v2di)__X, (__v2di)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32gather_pd (double const *__base, __m128i __index, const int __scale) +{ + __v2df __zero = _mm_setzero_pd (); + __v2df __mask = _mm_cmpeq_pd (__zero, __zero); + + return (__m128d) __builtin_ia32_gathersiv2df (_mm_undefined_pd (), + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32gather_pd (__m128d __src, double const *__base, __m128i __index, + __m128d __mask, const int __scale) +{ + return (__m128d) __builtin_ia32_gathersiv2df ((__v2df)__src, + __base, + (__v4si)__index, + (__v2df)__mask, + __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32gather_pd (double const *__base, __m128i __index, const int __scale) +{ + __v4df __zero = _mm256_setzero_pd (); + __v4df __mask = _mm256_cmp_pd (__zero, __zero, _CMP_EQ_OQ); + + return (__m256d) __builtin_ia32_gathersiv4df (_mm256_undefined_pd (), + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32gather_pd (__m256d __src, double const *__base, + __m128i __index, __m256d __mask, const int __scale) +{ + return (__m256d) __builtin_ia32_gathersiv4df ((__v4df)__src, + __base, + (__v4si)__index, + (__v4df)__mask, + __scale); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64gather_pd (double const *__base, __m128i __index, const int __scale) +{ + __v2df __src = _mm_setzero_pd (); + __v2df __mask = _mm_cmpeq_pd (__src, __src); + + return (__m128d) __builtin_ia32_gatherdiv2df (__src, + __base, + (__v2di)__index, + __mask, + __scale); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64gather_pd (__m128d __src, double const *__base, __m128i __index, + __m128d __mask, const int __scale) +{ + return (__m128d) __builtin_ia32_gatherdiv2df ((__v2df)__src, + __base, + (__v2di)__index, + (__v2df)__mask, + __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64gather_pd (double const *__base, __m256i __index, const int __scale) +{ + __v4df __src = _mm256_setzero_pd (); + __v4df __mask = _mm256_cmp_pd (__src, __src, _CMP_EQ_OQ); + + return (__m256d) __builtin_ia32_gatherdiv4df (__src, + __base, + (__v4di)__index, + __mask, + __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64gather_pd (__m256d __src, double const *__base, + __m256i __index, __m256d __mask, const int __scale) +{ + return (__m256d) __builtin_ia32_gatherdiv4df ((__v4df)__src, + __base, + (__v4di)__index, + (__v4df)__mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32gather_ps (float const *__base, __m128i __index, const int __scale) +{ + __v4sf __src = _mm_setzero_ps (); + __v4sf __mask = _mm_cmpeq_ps (__src, __src); + + return (__m128) __builtin_ia32_gathersiv4sf (__src, + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32gather_ps (__m128 __src, float const *__base, __m128i __index, + __m128 __mask, const int __scale) +{ + return (__m128) __builtin_ia32_gathersiv4sf ((__v4sf)__src, + __base, + (__v4si)__index, + (__v4sf)__mask, + __scale); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32gather_ps (float const *__base, __m256i __index, const int __scale) +{ + __v8sf __src = _mm256_setzero_ps (); + __v8sf __mask = _mm256_cmp_ps (__src, __src, _CMP_EQ_OQ); + + return (__m256) __builtin_ia32_gathersiv8sf (__src, + __base, + (__v8si)__index, + __mask, + __scale); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32gather_ps (__m256 __src, float const *__base, + __m256i __index, __m256 __mask, const int __scale) +{ + return (__m256) __builtin_ia32_gathersiv8sf ((__v8sf)__src, + __base, + (__v8si)__index, + (__v8sf)__mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64gather_ps (float const *__base, __m128i __index, const int __scale) +{ + __v4sf __src = _mm_setzero_ps (); + __v4sf __mask = _mm_cmpeq_ps (__src, __src); + + return (__m128) __builtin_ia32_gatherdiv4sf (__src, + __base, + (__v2di)__index, + __mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64gather_ps (__m128 __src, float const *__base, __m128i __index, + __m128 __mask, const int __scale) +{ + return (__m128) __builtin_ia32_gatherdiv4sf ((__v4sf)__src, + __base, + (__v2di)__index, + (__v4sf)__mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64gather_ps (float const *__base, __m256i __index, const int __scale) +{ + __v4sf __src = _mm_setzero_ps (); + __v4sf __mask = _mm_cmpeq_ps (__src, __src); + + return (__m128) __builtin_ia32_gatherdiv4sf256 (__src, + __base, + (__v4di)__index, + __mask, + __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64gather_ps (__m128 __src, float const *__base, + __m256i __index, __m128 __mask, const int __scale) +{ + return (__m128) __builtin_ia32_gatherdiv4sf256 ((__v4sf)__src, + __base, + (__v4di)__index, + (__v4sf)__mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32gather_epi64 (long long int const *__base, + __m128i __index, const int __scale) +{ + __v2di __src = __extension__ (__v2di){ 0, 0 }; + __v2di __mask = __extension__ (__v2di){ ~0, ~0 }; + + return (__m128i) __builtin_ia32_gathersiv2di (__src, + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32gather_epi64 (__m128i __src, long long int const *__base, + __m128i __index, __m128i __mask, const int __scale) +{ + return (__m128i) __builtin_ia32_gathersiv2di ((__v2di)__src, + __base, + (__v4si)__index, + (__v2di)__mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32gather_epi64 (long long int const *__base, + __m128i __index, const int __scale) +{ + __v4di __src = __extension__ (__v4di){ 0, 0, 0, 0 }; + __v4di __mask = __extension__ (__v4di){ ~0, ~0, ~0, ~0 }; + + return (__m256i) __builtin_ia32_gathersiv4di (__src, + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32gather_epi64 (__m256i __src, long long int const *__base, + __m128i __index, __m256i __mask, + const int __scale) +{ + return (__m256i) __builtin_ia32_gathersiv4di ((__v4di)__src, + __base, + (__v4si)__index, + (__v4di)__mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64gather_epi64 (long long int const *__base, + __m128i __index, const int __scale) +{ + __v2di __src = __extension__ (__v2di){ 0, 0 }; + __v2di __mask = __extension__ (__v2di){ ~0, ~0 }; + + return (__m128i) __builtin_ia32_gatherdiv2di (__src, + __base, + (__v2di)__index, + __mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64gather_epi64 (__m128i __src, long long int const *__base, + __m128i __index, __m128i __mask, const int __scale) +{ + return (__m128i) __builtin_ia32_gatherdiv2di ((__v2di)__src, + __base, + (__v2di)__index, + (__v2di)__mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64gather_epi64 (long long int const *__base, + __m256i __index, const int __scale) +{ + __v4di __src = __extension__ (__v4di){ 0, 0, 0, 0 }; + __v4di __mask = __extension__ (__v4di){ ~0, ~0, ~0, ~0 }; + + return (__m256i) __builtin_ia32_gatherdiv4di (__src, + __base, + (__v4di)__index, + __mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64gather_epi64 (__m256i __src, long long int const *__base, + __m256i __index, __m256i __mask, + const int __scale) +{ + return (__m256i) __builtin_ia32_gatherdiv4di ((__v4di)__src, + __base, + (__v4di)__index, + (__v4di)__mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32gather_epi32 (int const *__base, __m128i __index, const int __scale) +{ + __v4si __src = __extension__ (__v4si){ 0, 0, 0, 0 }; + __v4si __mask = __extension__ (__v4si){ ~0, ~0, ~0, ~0 }; + + return (__m128i) __builtin_ia32_gathersiv4si (__src, + __base, + (__v4si)__index, + __mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32gather_epi32 (__m128i __src, int const *__base, __m128i __index, + __m128i __mask, const int __scale) +{ + return (__m128i) __builtin_ia32_gathersiv4si ((__v4si)__src, + __base, + (__v4si)__index, + (__v4si)__mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32gather_epi32 (int const *__base, __m256i __index, const int __scale) +{ + __v8si __src = __extension__ (__v8si){ 0, 0, 0, 0, 0, 0, 0, 0 }; + __v8si __mask = __extension__ (__v8si){ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }; + + return (__m256i) __builtin_ia32_gathersiv8si (__src, + __base, + (__v8si)__index, + __mask, + __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32gather_epi32 (__m256i __src, int const *__base, + __m256i __index, __m256i __mask, + const int __scale) +{ + return (__m256i) __builtin_ia32_gathersiv8si ((__v8si)__src, + __base, + (__v8si)__index, + (__v8si)__mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64gather_epi32 (int const *__base, __m128i __index, const int __scale) +{ + __v4si __src = __extension__ (__v4si){ 0, 0, 0, 0 }; + __v4si __mask = __extension__ (__v4si){ ~0, ~0, ~0, ~0 }; + + return (__m128i) __builtin_ia32_gatherdiv4si (__src, + __base, + (__v2di)__index, + __mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64gather_epi32 (__m128i __src, int const *__base, __m128i __index, + __m128i __mask, const int __scale) +{ + return (__m128i) __builtin_ia32_gatherdiv4si ((__v4si)__src, + __base, + (__v2di)__index, + (__v4si)__mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64gather_epi32 (int const *__base, __m256i __index, const int __scale) +{ + __v4si __src = __extension__ (__v4si){ 0, 0, 0, 0 }; + __v4si __mask = __extension__ (__v4si){ ~0, ~0, ~0, ~0 }; + + return (__m128i) __builtin_ia32_gatherdiv4si256 (__src, + __base, + (__v4di)__index, + __mask, + __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64gather_epi32 (__m128i __src, int const *__base, + __m256i __index, __m128i __mask, + const int __scale) +{ + return (__m128i) __builtin_ia32_gatherdiv4si256 ((__v4si)__src, + __base, + (__v4di)__index, + (__v4si)__mask, + __scale); +} +#else /* __OPTIMIZE__ */ +#define _mm_i32gather_pd(BASE, INDEX, SCALE) \ + (__m128d) __builtin_ia32_gathersiv2df ((__v2df) _mm_setzero_pd (), \ + (double const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v2df) \ + _mm_cmpeq_pd (_mm_setzero_pd (),\ + _mm_setzero_pd ()),\ + (int) (SCALE)) + +#define _mm_mask_i32gather_pd(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128d) __builtin_ia32_gathersiv2df ((__v2df)(__m128d) (SRC), \ + (double const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v2df)(__m128d) (MASK), \ + (int) (SCALE)) + +#define _mm256_i32gather_pd(BASE, INDEX, SCALE) \ + (__m256d) __builtin_ia32_gathersiv4df ((__v4df) _mm256_setzero_pd (), \ + (double const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4df) \ + _mm256_cmp_pd (_mm256_setzero_pd (),\ + _mm256_setzero_pd (),\ + _CMP_EQ_OQ), \ + (int) (SCALE)) + +#define _mm256_mask_i32gather_pd(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256d) __builtin_ia32_gathersiv4df ((__v4df)(__m256d) (SRC), \ + (double const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4df)(__m256d) (MASK), \ + (int) (SCALE)) + +#define _mm_i64gather_pd(BASE, INDEX, SCALE) \ + (__m128d) __builtin_ia32_gatherdiv2df ((__v2df) _mm_setzero_pd (), \ + (double const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v2df) \ + _mm_cmpeq_pd (_mm_setzero_pd (),\ + _mm_setzero_pd ()),\ + (int) (SCALE)) + +#define _mm_mask_i64gather_pd(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128d) __builtin_ia32_gatherdiv2df ((__v2df)(__m128d) (SRC), \ + (double const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v2df)(__m128d) (MASK), \ + (int) (SCALE)) + +#define _mm256_i64gather_pd(BASE, INDEX, SCALE) \ + (__m256d) __builtin_ia32_gatherdiv4df ((__v4df) _mm256_setzero_pd (), \ + (double const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4df) \ + _mm256_cmp_pd (_mm256_setzero_pd (),\ + _mm256_setzero_pd (),\ + _CMP_EQ_OQ), \ + (int) (SCALE)) + +#define _mm256_mask_i64gather_pd(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256d) __builtin_ia32_gatherdiv4df ((__v4df)(__m256d) (SRC), \ + (double const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4df)(__m256d) (MASK), \ + (int) (SCALE)) + +#define _mm_i32gather_ps(BASE, INDEX, SCALE) \ + (__m128) __builtin_ia32_gathersiv4sf ((__v4sf) _mm_setzero_ps (), \ + (float const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4sf) \ + _mm_cmpeq_ps (_mm_setzero_ps (),\ + _mm_setzero_ps ()),\ + (int) (SCALE)) + +#define _mm_mask_i32gather_ps(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128) __builtin_ia32_gathersiv4sf ((__v4sf)(__m128) (SRC), \ + (float const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4sf)(__m128) (MASK), \ + (int) (SCALE)) + +#define _mm256_i32gather_ps(BASE, INDEX, SCALE) \ + (__m256) __builtin_ia32_gathersiv8sf ((__v8sf) _mm256_setzero_ps (), \ + (float const *) (BASE), \ + (__v8si)(__m256i) (INDEX), \ + (__v8sf) \ + _mm256_cmp_ps (_mm256_setzero_ps (),\ + _mm256_setzero_ps (),\ + _CMP_EQ_OQ), \ + (int) (SCALE)) + +#define _mm256_mask_i32gather_ps(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256) __builtin_ia32_gathersiv8sf ((__v8sf)(__m256) (SRC), \ + (float const *) (BASE), \ + (__v8si)(__m256i) (INDEX), \ + (__v8sf)(__m256) (MASK), \ + (int) (SCALE)) + +#define _mm_i64gather_ps(BASE, INDEX, SCALE) \ + (__m128) __builtin_ia32_gatherdiv4sf ((__v4sf) _mm_setzero_pd (), \ + (float const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v4sf) \ + _mm_cmpeq_ps (_mm_setzero_ps (),\ + _mm_setzero_ps ()),\ + (int) (SCALE)) + +#define _mm_mask_i64gather_ps(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128) __builtin_ia32_gatherdiv4sf ((__v4sf)(__m128) (SRC), \ + (float const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v4sf)(__m128) (MASK), \ + (int) (SCALE)) + +#define _mm256_i64gather_ps(BASE, INDEX, SCALE) \ + (__m128) __builtin_ia32_gatherdiv4sf256 ((__v4sf) _mm_setzero_ps (), \ + (float const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4sf) \ + _mm_cmpeq_ps (_mm_setzero_ps (),\ + _mm_setzero_ps ()),\ + (int) (SCALE)) + +#define _mm256_mask_i64gather_ps(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128) __builtin_ia32_gatherdiv4sf256 ((__v4sf)(__m128) (SRC), \ + (float const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4sf)(__m128) (MASK), \ + (int) (SCALE)) + +#define _mm_i32gather_epi64(BASE, INDEX, SCALE) \ + (__m128i) __builtin_ia32_gathersiv2di ((__v2di) _mm_setzero_si128 (), \ + (long long const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v2di)_mm_set1_epi64x (-1), \ + (int) (SCALE)) + +#define _mm_mask_i32gather_epi64(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128i) __builtin_ia32_gathersiv2di ((__v2di)(__m128i) (SRC), \ + (long long const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v2di)(__m128i) (MASK), \ + (int) (SCALE)) + +#define _mm256_i32gather_epi64(BASE, INDEX, SCALE) \ + (__m256i) __builtin_ia32_gathersiv4di ((__v4di) _mm256_setzero_si256 (), \ + (long long const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4di)_mm256_set1_epi64x (-1), \ + (int) (SCALE)) + +#define _mm256_mask_i32gather_epi64(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256i) __builtin_ia32_gathersiv4di ((__v4di)(__m256i) (SRC), \ + (long long const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4di)(__m256i) (MASK), \ + (int) (SCALE)) + +#define _mm_i64gather_epi64(BASE, INDEX, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv2di ((__v2di) _mm_setzero_si128 (), \ + (long long const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v2di)_mm_set1_epi64x (-1), \ + (int) (SCALE)) + +#define _mm_mask_i64gather_epi64(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv2di ((__v2di)(__m128i) (SRC), \ + (long long const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v2di)(__m128i) (MASK), \ + (int) (SCALE)) + +#define _mm256_i64gather_epi64(BASE, INDEX, SCALE) \ + (__m256i) __builtin_ia32_gatherdiv4di ((__v4di) _mm256_setzero_si256 (), \ + (long long const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4di)_mm256_set1_epi64x (-1), \ + (int) (SCALE)) + +#define _mm256_mask_i64gather_epi64(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256i) __builtin_ia32_gatherdiv4di ((__v4di)(__m256i) (SRC), \ + (long long const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4di)(__m256i) (MASK), \ + (int) (SCALE)) + +#define _mm_i32gather_epi32(BASE, INDEX, SCALE) \ + (__m128i) __builtin_ia32_gathersiv4si ((__v4si) _mm_setzero_si128 (), \ + (int const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4si)_mm_set1_epi32 (-1), \ + (int) (SCALE)) + +#define _mm_mask_i32gather_epi32(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128i) __builtin_ia32_gathersiv4si ((__v4si)(__m128i) (SRC), \ + (int const *) (BASE), \ + (__v4si)(__m128i) (INDEX), \ + (__v4si)(__m128i) (MASK), \ + (int) (SCALE)) + +#define _mm256_i32gather_epi32(BASE, INDEX, SCALE) \ + (__m256i) __builtin_ia32_gathersiv8si ((__v8si) _mm256_setzero_si256 (), \ + (int const *) (BASE), \ + (__v8si)(__m256i) (INDEX), \ + (__v8si)_mm256_set1_epi32 (-1), \ + (int) (SCALE)) + +#define _mm256_mask_i32gather_epi32(SRC, BASE, INDEX, MASK, SCALE) \ + (__m256i) __builtin_ia32_gathersiv8si ((__v8si)(__m256i) (SRC), \ + (int const *) (BASE), \ + (__v8si)(__m256i) (INDEX), \ + (__v8si)(__m256i) (MASK), \ + (int) (SCALE)) + +#define _mm_i64gather_epi32(BASE, INDEX, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv4si ((__v4si) _mm_setzero_si128 (), \ + (int const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v4si)_mm_set1_epi32 (-1), \ + (int) (SCALE)) + +#define _mm_mask_i64gather_epi32(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv4si ((__v4si)(__m128i) (SRC), \ + (int const *) (BASE), \ + (__v2di)(__m128i) (INDEX), \ + (__v4si)(__m128i) (MASK), \ + (int) (SCALE)) + +#define _mm256_i64gather_epi32(BASE, INDEX, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv4si256 ((__v4si) _mm_setzero_si128 (), \ + (int const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4si)_mm_set1_epi32(-1), \ + (int) (SCALE)) + +#define _mm256_mask_i64gather_epi32(SRC, BASE, INDEX, MASK, SCALE) \ + (__m128i) __builtin_ia32_gatherdiv4si256 ((__v4si)(__m128i) (SRC), \ + (int const *) (BASE), \ + (__v4di)(__m256i) (INDEX), \ + (__v4si)(__m128i) (MASK), \ + (int) (SCALE)) +#endif /* __OPTIMIZE__ */ + +#define _MM_REDUCE_OPERATOR_BASIC_EPI16(op) \ + __v8hi __T1 = (__v8hi)__W; \ + __v8hi __T2 = __builtin_shufflevector (__T1, __T1, 4, 5, 6, 7, 4, 5, 6, 7); \ + __v8hi __T3 = __T1 op __T2; \ + __v8hi __T4 = __builtin_shufflevector (__T3, __T3, 2, 3, 2, 3, 4, 5, 6, 7); \ + __v8hi __T5 = __T3 op __T4; \ + __v8hi __T6 = __builtin_shufflevector (__T5, __T5, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T7 = __T5 op __T6; \ + return __T7[0] + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_add_epi16 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI16 (+); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_mul_epi16 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI16 (*); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_and_epi16 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI16 (&); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_or_epi16 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI16 (|); +} + +#define _MM_REDUCE_OPERATOR_MAX_MIN_EP16(op) \ + __m128i __T1 = (__m128i)__builtin_shufflevector ((__v8hi)__V, \ + (__v8hi)__V, 4, 5, 6, 7, 4, 5, 6, 7); \ + __m128i __T2 = _mm_##op (__V, __T1); \ + __m128i __T3 = (__m128i)__builtin_shufflevector ((__v8hi)__T2, \ + (__v8hi)__T2, 2, 3, 2, 3, 4, 5, 6, 7); \ + __m128i __T4 = _mm_##op (__T2, __T3); \ + __m128i __T5 = (__m128i)__builtin_shufflevector ((__v8hi)__T4, \ + (__v8hi)__T4, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T6 = (__v8hi)_mm_##op (__T4, __T5); \ + return __T6[0] + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_max_epi16 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_max_epu16 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epu16); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_min_epi16 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_min_epu16 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epu16); +} + +#define _MM256_REDUCE_OPERATOR_BASIC_EPI16(op) \ + __v8hi __T1 = (__v8hi)_mm256_extracti128_si256 (__W, 0); \ + __v8hi __T2 = (__v8hi)_mm256_extracti128_si256 (__W, 1); \ + __v8hi __T3 = __T1 op __T2; \ + __v8hi __T4 = __builtin_shufflevector (__T3, __T3, 4, 5, 6, 7, 4, 5, 6, 7); \ + __v8hi __T5 = __T3 op __T4; \ + __v8hi __T6 = __builtin_shufflevector (__T5, __T5, 2, 3, 2, 3, 4, 5, 6, 7); \ + __v8hi __T7 = __T5 op __T6; \ + __v8hi __T8 = __builtin_shufflevector (__T7, __T7, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T9 = __T7 op __T8; \ + return __T9[0] + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_add_epi16 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI16 (+); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_mul_epi16 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI16 (*); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_and_epi16 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI16 (&); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_or_epi16 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI16 (|); +} + +#define _MM256_REDUCE_OPERATOR_MAX_MIN_EP16(op) \ + __m128i __T1 = _mm256_extracti128_si256 (__V, 0); \ + __m128i __T2 = _mm256_extracti128_si256 (__V, 1); \ + __m128i __T3 = _mm_##op (__T1, __T2); \ + __m128i __T4 = (__m128i)__builtin_shufflevector ((__v8hi)__T3, \ + (__v8hi)__T3, 4, 5, 6, 7, 4, 5, 6, 7); \ + __m128i __T5 = _mm_##op (__T3, __T4); \ + __m128i __T6 = (__m128i)__builtin_shufflevector ((__v8hi)__T5, \ + (__v8hi)__T5, 2, 3, 2, 3, 4, 5, 6, 7); \ + __m128i __T7 = _mm_##op (__T5, __T6); \ + __m128i __T8 = (__m128i)__builtin_shufflevector ((__v8hi)__T7, \ + (__v8hi)__T7, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T9 = (__v8hi)_mm_##op (__T7, __T8); \ + return __T9[0] + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_max_epi16 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_max_epu16 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epu16); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_min_epi16 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_min_epu16 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epu16); +} + +#define _MM_REDUCE_OPERATOR_BASIC_EPI8(op) \ + __v16qi __T1 = (__v16qi)__W; \ + __v16qi __T2 = __builtin_shufflevector (__T1, __T1, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T3 = __T1 op __T2; \ + __v16qi __T4 = __builtin_shufflevector (__T3, __T3, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T5 = __T3 op __T4; \ + __v16qi __T6 = __builtin_shufflevector (__T5, __T5, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T7 = __T5 op __T6; \ + __v16qi __T8 = __builtin_shufflevector (__T7, __T7, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T9 = __T7 op __T8; \ + return __T9[0] + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_add_epi8 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI8 (+); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_mul_epi8 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI8 (*); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_and_epi8 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI8 (&); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_or_epi8 (__m128i __W) +{ + _MM_REDUCE_OPERATOR_BASIC_EPI8 (|); +} + +#define _MM_REDUCE_OPERATOR_MAX_MIN_EP8(op) \ + __m128i __T1 = (__m128i)__builtin_shufflevector ((__v16qi)__V, (__v16qi)__V, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T2 = _mm_##op (__V, __T1); \ + __m128i __T3 = (__m128i)__builtin_shufflevector ((__v16qi)__T2, \ + (__v16qi)__T2, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T4 = _mm_##op (__T2, __T3); \ + __m128i __T5 = (__m128i)__builtin_shufflevector ((__v16qi)__T4, \ + (__v16qi)__T4, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T6 = _mm_##op (__T4, __T5); \ + __m128i __T7 = (__m128i)__builtin_shufflevector ((__v16qi)__T6, \ + (__v16qi)__T6, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T8 = (__v16qi)_mm_##op (__T6, __T7); \ + return __T8[0] + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_max_epi8 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_max_epu8 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epu8); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_min_epi8 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_min_epu8 (__m128i __V) +{ + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epu8); +} + +#define _MM256_REDUCE_OPERATOR_BASIC_EPI8(op) \ + __v16qi __T1 = (__v16qi)_mm256_extracti128_si256 (__W, 0); \ + __v16qi __T2 = (__v16qi)_mm256_extracti128_si256 (__W, 1); \ + __v16qi __T3 = __T1 op __T2; \ + __v16qi __T4 = __builtin_shufflevector (__T3, __T3, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T5 = __T3 op __T4; \ + __v16qi __T6 = __builtin_shufflevector (__T5, __T5, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T7 = __T5 op __T6; \ + __v16qi __T8 = __builtin_shufflevector (__T7, __T7, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T9 = __T7 op __T8; \ + __v16qi __T10 = __builtin_shufflevector (__T9, __T9, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T11 = __T9 op __T10; \ + return __T11[0] + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_add_epi8 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI8 (+); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_mul_epi8 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI8 (*); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_and_epi8 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI8 (&); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_or_epi8 (__m256i __W) +{ + _MM256_REDUCE_OPERATOR_BASIC_EPI8 (|); +} + +#define _MM256_REDUCE_OPERATOR_MAX_MIN_EP8(op) \ + __m128i __T1 = _mm256_extracti128_si256 (__V, 0); \ + __m128i __T2 = _mm256_extracti128_si256 (__V, 1); \ + __m128i __T3 = _mm_##op (__T1, __T2); \ + __m128i __T4 = (__m128i)__builtin_shufflevector ((__v16qi)__T3, \ + (__v16qi)__T3, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T5 = _mm_##op (__T3, __T4); \ + __m128i __T6 = (__m128i)__builtin_shufflevector ((__v16qi)__T5, \ + (__v16qi)__T5, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T7 = _mm_##op (__T5, __T6); \ + __m128i __T8 = (__m128i)__builtin_shufflevector ((__v16qi)__T7, \ + (__v16qi)__T5, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T9 = _mm_##op (__T7, __T8); \ + __m128i __T10 = (__m128i)__builtin_shufflevector ((__v16qi)__T9, \ + (__v16qi)__T9, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T11 = (__v16qi)_mm_##op (__T9, __T10); \ + return __T11[0] + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_max_epi8 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_max_epu8 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epu8); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_min_epi8 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_min_epu8 (__m256i __V) +{ + _MM256_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epu8); +} + +#ifdef __DISABLE_AVX2__ +#undef __DISABLE_AVX2__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX2__ */ + +#endif /* _AVX2INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx5124fmapsintrin.h b/template/sysroot/include/avx5124fmapsintrin.h new file mode 100644 index 0000000..842f1fc --- /dev/null +++ b/template/sysroot/include/avx5124fmapsintrin.h @@ -0,0 +1,216 @@ +/* Copyright (C) 2015-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX5124FMAPSINTRIN_H_INCLUDED +#define _AVX5124FMAPSINTRIN_H_INCLUDED + +#ifndef __AVX5124FMAPS__ +#pragma GCC push_options +#pragma GCC target("avx5124fmaps,evex512") +#define __DISABLE_AVX5124FMAPS__ +#endif /* __AVX5124FMAPS__ */ + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_4fmadd_ps (__m512 __A, __m512 __B, __m512 __C, + __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fmaddps ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_4fmadd_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F, + (__v16sf) __A, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_4fmadd_ps (__mmask16 __U, + __m512 __A, __m512 __B, __m512 __C, + __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F, + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_4fmadd_ss (__m128 __A, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fmaddss ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_4fmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F, + (__v4sf) __A, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_4fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F, + (__v4sf) _mm_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_4fnmadd_ps (__m512 __A, __m512 __B, __m512 __C, + __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fnmaddps ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_4fnmadd_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F, + (__v16sf) __A, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_4fnmadd_ps (__mmask16 __U, + __m512 __A, __m512 __B, __m512 __C, + __m512 __D, __m512 __E, __m128 *__F) +{ + return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B, + (__v16sf) __C, + (__v16sf) __D, + (__v16sf) __E, + (__v16sf) __A, + (const __v4sf *) __F, + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_4fnmadd_ss (__m128 __A, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fnmaddss ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_4fnmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F, + (__v4sf) __A, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_4fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C, + __m128 __D, __m128 __E, __m128 *__F) +{ + return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B, + (__v4sf) __C, + (__v4sf) __D, + (__v4sf) __E, + (__v4sf) __A, + (const __v4sf *) __F, + (__v4sf) _mm_setzero_ps (), + (__mmask8) __U); +} + +#ifdef __DISABLE_AVX5124FMAPS__ +#undef __DISABLE_AVX5124FMAPS__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX5124FMAPS__ */ + +#endif /* _AVX5124FMAPSINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx5124vnniwintrin.h b/template/sysroot/include/avx5124vnniwintrin.h new file mode 100644 index 0000000..57df9b2 --- /dev/null +++ b/template/sysroot/include/avx5124vnniwintrin.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2015-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX5124VNNIWINTRIN_H_INCLUDED +#define _AVX5124VNNIWINTRIN_H_INCLUDED + +#ifndef __AVX5124VNNIW__ +#pragma GCC push_options +#pragma GCC target("avx5124vnniw,evex512") +#define __DISABLE_AVX5124VNNIW__ +#endif /* __AVX5124VNNIW__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_4dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C, + __m512i __D, __m512i __E, __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssd ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_4dpwssd_epi32 (__m512i __A, __mmask16 __U, __m512i __B, + __m512i __C, __m512i __D, __m512i __E, + __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F, + (__v16si) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_4dpwssd_epi32 (__mmask16 __U, __m512i __A, __m512i __B, + __m512i __C, __m512i __D, __m512i __E, + __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F, + (__v16si) _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_4dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C, + __m512i __D, __m512i __E, __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssds ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_4dpwssds_epi32 (__m512i __A, __mmask16 __U, __m512i __B, + __m512i __C, __m512i __D, __m512i __E, + __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F, + (__v16si) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_4dpwssds_epi32 (__mmask16 __U, __m512i __A, __m512i __B, + __m512i __C, __m512i __D, __m512i __E, + __m128i *__F) +{ + return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B, + (__v16si) __C, + (__v16si) __D, + (__v16si) __E, + (__v16si) __A, + (const __v4si *) __F, + (__v16si) _mm512_setzero_ps (), + (__mmask16) __U); +} + +#ifdef __DISABLE_AVX5124VNNIW__ +#undef __DISABLE_AVX5124VNNIW__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX5124VNNIW__ */ + +#endif /* _AVX5124VNNIWINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512bf16intrin.h b/template/sysroot/include/avx512bf16intrin.h new file mode 100644 index 0000000..93bed30 --- /dev/null +++ b/template/sysroot/include/avx512bf16intrin.h @@ -0,0 +1,163 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512BF16INTRIN_H_INCLUDED +#define _AVX512BF16INTRIN_H_INCLUDED + +#if !defined (__AVX512BF16__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bf16,no-evex512") +#define __DISABLE_AVX512BF16__ +#endif /* __AVX512BF16__ */ + +/* Convert One BF16 Data to One Single Float Data. */ +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsbh_ss (__bf16 __A) +{ + return __builtin_ia32_cvtbf2sf (__A); +} + +#ifdef __DISABLE_AVX512BF16__ +#undef __DISABLE_AVX512BF16__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BF16__ */ + +#if !defined (__AVX512BF16__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bf16,evex512") +#define __DISABLE_AVX512BF16_512__ +#endif /* __AVX512BF16_512__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef __bf16 __v32bf __attribute__ ((__vector_size__ (64))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef __bf16 __m512bh __attribute__ ((__vector_size__ (64), __may_alias__)); + +/* vcvtne2ps2bf16 */ + +extern __inline __m512bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtne2ps_pbh (__m512 __A, __m512 __B) +{ + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf(__A, __B); +} + +extern __inline __m512bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtne2ps_pbh (__m512bh __A, __mmask32 __B, __m512 __C, __m512 __D) +{ + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_mask(__C, __D, __A, __B); +} + +extern __inline __m512bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtne2ps_pbh (__mmask32 __A, __m512 __B, __m512 __C) +{ + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_maskz(__B, __C, __A); +} + +/* vcvtneps2bf16 */ + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtneps_pbh (__m512 __A) +{ + return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf(__A); +} + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtneps_pbh (__m256bh __A, __mmask16 __B, __m512 __C) +{ + return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_mask(__C, __A, __B); +} + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtneps_pbh (__mmask16 __A, __m512 __B) +{ + return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_maskz(__B, __A); +} + +/* vdpbf16ps */ + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dpbf16_ps (__m512 __A, __m512bh __B, __m512bh __C) +{ + return (__m512)__builtin_ia32_dpbf16ps_v16sf(__A, __B, __C); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dpbf16_ps (__m512 __A, __mmask16 __B, __m512bh __C, __m512bh __D) +{ + return (__m512)__builtin_ia32_dpbf16ps_v16sf_mask(__A, __C, __D, __B); +} + +extern __inline __m512 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dpbf16_ps (__mmask16 __A, __m512 __B, __m512bh __C, __m512bh __D) +{ + return (__m512)__builtin_ia32_dpbf16ps_v16sf_maskz(__B, __C, __D, __A); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpbh_ps (__m256bh __A) +{ + return (__m512)_mm512_castsi512_ps ((__m512i)_mm512_slli_epi32 ( + (__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16)); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpbh_ps (__mmask16 __U, __m256bh __A) +{ + return (__m512)_mm512_castsi512_ps ((__m512i) _mm512_slli_epi32 ( + (__m512i)_mm512_maskz_cvtepi16_epi32 ( + (__mmask16)__U, (__m256i)__A), 16)); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpbh_ps (__m512 __S, __mmask16 __U, __m256bh __A) +{ + return (__m512)_mm512_castsi512_ps ((__m512i)(_mm512_mask_slli_epi32 ( + (__m512i)__S, (__mmask16)__U, + (__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16))); +} + +#ifdef __DISABLE_AVX512BF16_512__ +#undef __DISABLE_AVX512BF16_512__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BF16_512__ */ + +#endif /* _AVX512BF16INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512bf16vlintrin.h b/template/sysroot/include/avx512bf16vlintrin.h new file mode 100644 index 0000000..1cb9592 --- /dev/null +++ b/template/sysroot/include/avx512bf16vlintrin.h @@ -0,0 +1,276 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512BF16VLINTRIN_H_INCLUDED +#define _AVX512BF16VLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512BF16__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bf16,avx512vl,no-evex512") +#define __DISABLE_AVX512BF16VL__ +#endif /* __AVX512BF16__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef __bf16 __v16bf __attribute__ ((__vector_size__ (32))); +typedef __bf16 __v8bf __attribute__ ((__vector_size__ (16))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef __bf16 __m256bh __attribute__ ((__vector_size__ (32), __may_alias__)); +typedef __bf16 __m128bh __attribute__ ((__vector_size__ (16), __may_alias__)); + +typedef __bf16 __bfloat16; + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_castsi128_ps(__m128i __A) +{ + return (__m128) __A; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_castsi256_ps (__m256i __A) +{ + return (__m256) __A; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_slli_epi32 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_slli_epi32 (__m256i __A, int __B) +{ + return (__m256i)__builtin_ia32_pslldi256 ((__v8si)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_cvtepi16_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxwd128 ((__v8hi)__X); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_cvtepi16_epi32 (__m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxwd256 ((__v8hi)__X); +} + +#define _mm256_cvtneps_pbh(A) \ + (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (A) +#define _mm_cvtneps_pbh(A) \ + (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (A) + +/* vcvtne2ps2bf16 */ + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtne2ps_pbh (__m256 __A, __m256 __B) +{ + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf(__A, __B); +} + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtne2ps_pbh (__m256bh __A, __mmask16 __B, __m256 __C, __m256 __D) +{ + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_mask(__C, __D, __A, __B); +} + +extern __inline __m256bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtne2ps_pbh (__mmask16 __A, __m256 __B, __m256 __C) +{ + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_maskz(__B, __C, __A); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtne2ps_pbh (__m128 __A, __m128 __B) +{ + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf(__A, __B); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtne2ps_pbh (__m128bh __A, __mmask8 __B, __m128 __C, __m128 __D) +{ + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_mask(__C, __D, __A, __B); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtne2ps_pbh (__mmask8 __A, __m128 __B, __m128 __C) +{ + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_maskz(__B, __C, __A); +} + +/* vcvtneps2bf16 */ + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m256 __C) +{ + return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_mask(__C, __A, __B); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtneps_pbh (__mmask8 __A, __m256 __B) +{ + return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_maskz(__B, __A); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m128 __C) +{ + return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_mask(__C, __A, __B); +} + +extern __inline __m128bh +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtneps_pbh (__mmask8 __A, __m128 __B) +{ + return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_maskz(__B, __A); +} + +/* vdpbf16ps */ + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbf16_ps (__m256 __A, __m256bh __B, __m256bh __C) +{ + return (__m256)__builtin_ia32_dpbf16ps_v8sf(__A, __B, __C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dpbf16_ps (__m256 __A, __mmask8 __B, __m256bh __C, __m256bh __D) +{ + return (__m256)__builtin_ia32_dpbf16ps_v8sf_mask(__A, __C, __D, __B); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dpbf16_ps (__mmask8 __A, __m256 __B, __m256bh __C, __m256bh __D) +{ + return (__m256)__builtin_ia32_dpbf16ps_v8sf_maskz(__B, __C, __D, __A); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbf16_ps (__m128 __A, __m128bh __B, __m128bh __C) +{ + return (__m128)__builtin_ia32_dpbf16ps_v4sf(__A, __B, __C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dpbf16_ps (__m128 __A, __mmask8 __B, __m128bh __C, __m128bh __D) +{ + return (__m128)__builtin_ia32_dpbf16ps_v4sf_mask(__A, __C, __D, __B); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dpbf16_ps (__mmask8 __A, __m128 __B, __m128bh __C, __m128bh __D) +{ + return (__m128)__builtin_ia32_dpbf16ps_v4sf_maskz(__B, __C, __D, __A); +} + +extern __inline __bf16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtness_sbh (float __A) +{ + __v4sf __V = {__A, 0, 0, 0}; + __v8bf __R = __builtin_ia32_cvtneps2bf16_v4sf_mask ((__v4sf)__V, + (__v8bf)_mm_avx512_undefined_si128 (), (__mmask8)-1); + return __R[0]; +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpbh_ps (__m128bh __A) +{ + return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 ( + (__m128i)_mm_avx512_cvtepi16_epi32 ((__m128i)__A), 16)); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpbh_ps (__m128bh __A) +{ + return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 ( + (__m256i)_mm256_avx512_cvtepi16_epi32 ((__m128i)__A), 16)); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A) +{ + return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 ( + (__m128i)_mm_maskz_cvtepi16_epi32 ( + (__mmask8)__U, (__m128i)__A), 16)); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A) +{ + return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 ( + (__m256i)_mm256_maskz_cvtepi16_epi32 ( + (__mmask8)__U, (__m128i)__A), 16)); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpbh_ps (__m128 __S, __mmask8 __U, __m128bh __A) +{ + return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_mask_slli_epi32 ( + (__m128i)__S, (__mmask8)__U, (__m128i)_mm_avx512_cvtepi16_epi32 ( + (__m128i)__A), 16)); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpbh_ps (__m256 __S, __mmask8 __U, __m128bh __A) +{ + return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_mask_slli_epi32 ( + (__m256i)__S, (__mmask8)__U, (__m256i)_mm256_avx512_cvtepi16_epi32 ( + (__m128i)__A), 16)); +} + +#ifdef __DISABLE_AVX512BF16VL__ +#undef __DISABLE_AVX512BF16VL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BF16VL__ */ + +#endif /* _AVX512BF16VLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512bitalgintrin.h b/template/sysroot/include/avx512bitalgintrin.h new file mode 100644 index 0000000..dbabd7e --- /dev/null +++ b/template/sysroot/include/avx512bitalgintrin.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX512BITALGINTRIN_H_INCLUDED +#define _AVX512BITALGINTRIN_H_INCLUDED + +#if !defined (__AVX512BITALG__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bitalg,evex512") +#define __DISABLE_AVX512BITALG__ +#endif /* __AVX512BITALG__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_popcnt_epi8 (__m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountb_v64qi ((__v64qi) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_popcnt_epi16 (__m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountw_v32hi ((__v32hi) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_popcnt_epi8 (__m512i __W, __mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_popcnt_epi8 (__mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_popcnt_epi16 (__m512i __W, __mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_popcnt_epi16 (__mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __mmask64 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_bitshuffle_epi64_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_bitshuffle_epi64_mask (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) __M); +} + +#ifdef __DISABLE_AVX512BITALG__ +#undef __DISABLE_AVX512BITALG__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BITALG__ */ + +#endif /* _AVX512BITALGINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512bitalgvlintrin.h b/template/sysroot/include/avx512bitalgvlintrin.h new file mode 100644 index 0000000..4dd758e --- /dev/null +++ b/template/sysroot/include/avx512bitalgvlintrin.h @@ -0,0 +1,180 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX512BITALGVLINTRIN_H_INCLUDED +#define _AVX512BITALGVLINTRIN_H_INCLUDED + +#if !defined(__AVX512BITALG__) || !defined(__AVX512VL__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bitalg,avx512vl,no-evex512") +#define __DISABLE_AVX512BITALGVL__ +#endif /* __AVX512BITALGVL__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_popcnt_epi8 (__m256i __W, __mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_popcnt_epi8 (__mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __mmask32 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bitshuffle_epi64_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_bitshuffle_epi64_mask (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) __M); +} + +extern __inline __mmask16 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bitshuffle_epi64_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_bitshuffle_epi64_mask (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_popcnt_epi8 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountb_v32qi ((__v32qi) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_popcnt_epi16 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountw_v16hi ((__v16hi) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountb_v16qi ((__v16qi) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountw_v8hi ((__v8hi) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_popcnt_epi16 (__m256i __W, __mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_popcnt_epi16 (__mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_popcnt_epi8 (__m128i __W, __mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_popcnt_epi8 (__mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_popcnt_epi16 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_popcnt_epi16 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} +#ifdef __DISABLE_AVX512BITALGVL__ +#undef __DISABLE_AVX512BITALGVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BITALGVL__ */ + +#endif /* _AVX512BITALGVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512bwintrin.h b/template/sysroot/include/avx512bwintrin.h new file mode 100644 index 0000000..8991c9c --- /dev/null +++ b/template/sysroot/include/avx512bwintrin.h @@ -0,0 +1,3377 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512BWINTRIN_H_INCLUDED +#define _AVX512BWINTRIN_H_INCLUDED + +#if !defined (__AVX512BW__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bw,no-evex512") +#define __DISABLE_AVX512BW__ +#endif /* __AVX512BW__ */ + +typedef unsigned long long __mmask64; + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set_epi32 (int __q3, int __q2, int __q1, int __q0) +{ + return __extension__ (__m128i)(__v4si){ __q0, __q1, __q2, __q3 }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set_epi16 (short __q7, short __q6, short __q5, short __q4, + short __q3, short __q2, short __q1, short __q0) +{ + return __extension__ (__m128i)(__v8hi){ + __q0, __q1, __q2, __q3, __q4, __q5, __q6, __q7 }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set_epi8 (char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return __extension__ (__m128i)(__v16qi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15 + }; +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktest_mask32_u8 (__mmask32 __A, __mmask32 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_ktestcsi (__A, __B); + return (unsigned char) __builtin_ia32_ktestzsi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestz_mask32_u8 (__mmask32 __A, __mmask32 __B) +{ + return (unsigned char) __builtin_ia32_ktestzsi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestc_mask32_u8 (__mmask32 __A, __mmask32 __B) +{ + return (unsigned char) __builtin_ia32_ktestcsi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortest_mask32_u8 (__mmask32 __A, __mmask32 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_kortestcsi (__A, __B); + return (unsigned char) __builtin_ia32_kortestzsi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestz_mask32_u8 (__mmask32 __A, __mmask32 __B) +{ + return (unsigned char) __builtin_ia32_kortestzsi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestc_mask32_u8 (__mmask32 __A, __mmask32 __B) +{ + return (unsigned char) __builtin_ia32_kortestcsi (__A, __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kadd_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kaddsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtmask32_u32 (__mmask32 __A) +{ + return (unsigned int) __builtin_ia32_kmovd ((__mmask32) __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtu32_mask32 (unsigned int __A) +{ + return (__mmask32) __builtin_ia32_kmovd ((__mmask32) __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_load_mask32 (__mmask32 *__A) +{ + return (__mmask32) __builtin_ia32_kmovd (*__A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_store_mask32 (__mmask32 *__A, __mmask32 __B) +{ + *(__mmask32 *) __A = __builtin_ia32_kmovd (__B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_knot_mask32 (__mmask32 __A) +{ + return (__mmask32) __builtin_ia32_knotsi ((__mmask32) __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kor_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_korsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxnor_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kxnorsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxor_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kxorsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kand_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kandsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kandn_mask32 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kandnsi ((__mmask32) __A, (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kunpackw (__mmask32 __A, __mmask32 __B) +{ + return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A, + (__mmask32) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kunpackw_mask32 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A, + (__mmask32) __B); +} + +#if __OPTIMIZE__ +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftli_mask32 (__mmask32 __A, unsigned int __B) +{ + return (__mmask32) __builtin_ia32_kshiftlisi ((__mmask32) __A, + (__mmask8) __B); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftri_mask32 (__mmask32 __A, unsigned int __B) +{ + return (__mmask32) __builtin_ia32_kshiftrisi ((__mmask32) __A, + (__mmask8) __B); +} + +#else +#define _kshiftli_mask32(X, Y) \ + ((__mmask32) __builtin_ia32_kshiftlisi ((__mmask32)(X), (__mmask8)(Y))) + +#define _kshiftri_mask32(X, Y) \ + ((__mmask32) __builtin_ia32_kshiftrisi ((__mmask32)(X), (__mmask8)(Y))) + +#endif + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktest_mask64_u8 (__mmask64 __A, __mmask64 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_ktestcdi (__A, __B); + return (unsigned char) __builtin_ia32_ktestzdi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestz_mask64_u8 (__mmask64 __A, __mmask64 __B) +{ + return (unsigned char) __builtin_ia32_ktestzdi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestc_mask64_u8 (__mmask64 __A, __mmask64 __B) +{ + return (unsigned char) __builtin_ia32_ktestcdi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortest_mask64_u8 (__mmask64 __A, __mmask64 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_kortestcdi (__A, __B); + return (unsigned char) __builtin_ia32_kortestzdi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestz_mask64_u8 (__mmask64 __A, __mmask64 __B) +{ + return (unsigned char) __builtin_ia32_kortestzdi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestc_mask64_u8 (__mmask64 __A, __mmask64 __B) +{ + return (unsigned char) __builtin_ia32_kortestcdi (__A, __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kadd_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kadddi ((__mmask64) __A, (__mmask64) __B); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtmask64_u64 (__mmask64 __A) +{ + return (unsigned long long) __builtin_ia32_kmovq ((__mmask64) __A); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtu64_mask64 (unsigned long long __A) +{ + return (__mmask64) __builtin_ia32_kmovq ((__mmask64) __A); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_load_mask64 (__mmask64 *__A) +{ + return (__mmask64) __builtin_ia32_kmovq (*(__mmask64 *) __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_store_mask64 (__mmask64 *__A, __mmask64 __B) +{ + *(__mmask64 *) __A = __builtin_ia32_kmovq (__B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_knot_mask64 (__mmask64 __A) +{ + return (__mmask64) __builtin_ia32_knotdi ((__mmask64) __A); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kor_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kordi ((__mmask64) __A, (__mmask64) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxnor_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kxnordi ((__mmask64) __A, (__mmask64) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxor_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kxordi ((__mmask64) __A, (__mmask64) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kand_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kanddi ((__mmask64) __A, (__mmask64) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kandn_mask64 (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kandndi ((__mmask64) __A, (__mmask64) __B); +} + +#ifdef __DISABLE_AVX512BW__ +#undef __DISABLE_AVX512BW__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BW__ */ + +#if !defined (__AVX512BW__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512bw,evex512") +#define __DISABLE_AVX512BW_512__ +#endif /* __AVX512BW_512__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef short __v32hi __attribute__ ((__vector_size__ (64))); +typedef short __v32hi_u __attribute__ ((__vector_size__ (64), \ + __may_alias__, __aligned__ (1))); +typedef char __v64qi __attribute__ ((__vector_size__ (64))); +typedef char __v64qi_u __attribute__ ((__vector_size__ (64), \ + __may_alias__, __aligned__ (1))); + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_epi16 (__m512i __W, __mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdquhi512_mask ((__v32hi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_epi16 (__mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdquhi512_mask ((__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi16 (void const *__P) +{ + return (__m512i) (*(__v32hi_u *) __P); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_epi16 (__m512i __W, __mmask32 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddquhi512_mask ((const short *) __P, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_epi16 (__mmask32 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddquhi512_mask ((const short *) __P, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi16 (void *__P, __m512i __A) +{ + *(__v32hi_u *) __P = (__v32hi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_epi16 (void *__P, __mmask32 __U, __m512i __A) +{ + __builtin_ia32_storedquhi512_mask ((short *) __P, + (__v32hi) __A, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_epi8 (__m512i __W, __mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdquqi512_mask ((__v64qi) __A, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_epi8 (__mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdquqi512_mask ((__v64qi) __A, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kunpackd (__mmask64 __A, __mmask64 __B) +{ + return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A, + (__mmask64) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kunpackd_mask64 (__mmask32 __A, __mmask32 __B) +{ + return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A, + (__mmask64) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi8 (void const *__P) +{ + return (__m512i) (*(__v64qi_u *) __P); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_epi8 (__m512i __W, __mmask64 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddquqi512_mask ((const char *) __P, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_epi8 (__mmask64 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddquqi512_mask ((const char *) __P, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi8 (void *__P, __m512i __A) +{ + *(__v64qi_u *) __P = (__v64qi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_epi8 (void *__P, __mmask64 __U, __m512i __A) +{ + __builtin_ia32_storedquqi512_mask ((char *) __P, + (__v64qi) __A, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sad_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psadbw512 ((__v64qi) __A, + (__v64qi) __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi16_epi8 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) _mm256_undefined_si256(), + (__mmask32) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A) +{ + __builtin_ia32_pmovwb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi16_epi8 (__mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi16_epi8 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A, + (__v32qi)_mm256_undefined_si256(), + (__mmask32) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A) +{ + __builtin_ia32_pmovswb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A, + (__v32qi)__O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi16_epi8 (__mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A, + (__v32qi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi16_epi8 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A, + (__v32qi)_mm256_undefined_si256(), + (__mmask32) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A, + (__v32qi) __O, + __M); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A) +{ + __builtin_ia32_pmovuswb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi16_epi8 (__mmask32 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A, + (__v32qi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastb_epi8 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastb512_mask ((__v16qi) __A, + (__v64qi)_mm512_undefined_epi32(), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastb_epi8 (__m512i __O, __mmask64 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastb512_mask ((__v16qi) __A, + (__v64qi) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastb_epi8 (__mmask64 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastb512_mask ((__v16qi) __A, + (__v64qi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_set1_epi8 (__m512i __O, __mmask64 __M, char __A) +{ + return (__m512i) __builtin_ia32_pbroadcastb512_gpr_mask (__A, + (__v64qi) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_set1_epi8 (__mmask64 __M, char __A) +{ + return (__m512i) + __builtin_ia32_pbroadcastb512_gpr_mask (__A, + (__v64qi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastw_epi16 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastw512_mask ((__v8hi) __A, + (__v32hi)_mm512_undefined_epi32(), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastw_epi16 (__m512i __O, __mmask32 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastw512_mask ((__v8hi) __A, + (__v32hi) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastw_epi16 (__mmask32 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastw512_mask ((__v8hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_set1_epi16 (__m512i __O, __mmask32 __M, short __A) +{ + return (__m512i) __builtin_ia32_pbroadcastw512_gpr_mask (__A, + (__v32hi) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_set1_epi16 (__mmask32 __M, short __A) +{ + return (__m512i) + __builtin_ia32_pbroadcastw512_gpr_mask (__A, + (__v32hi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mulhrs_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mulhrs_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mulhrs_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mulhi_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mulhi_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mulhi_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mulhi_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mulhi_epu16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mulhi_epu16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mullo_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v32hu) __A * (__v32hu) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mullo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mullo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi8_epi16 (__m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi8_epi16 (__m512i __W, __mmask32 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi8_epi16 (__mmask32 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu8_epi16 (__m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu8_epi16 (__m512i __W, __mmask32 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu8_epi16 (__mmask32 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B, + (__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_epi16 (__mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B, + (__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_epi16 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarhi512_mask ((__v32hi) __B, + (__v32hi) __A, + (__v32hi) __W, + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_epi16 (__m512i __A, __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I + /* idx */ , + (__v32hi) __A, + (__v32hi) __B, + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_epi16 (__m512i __A, __mmask32 __U, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I + /* idx */ , + (__v32hi) __A, + (__v32hi) __B, + (__mmask32) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_epi16 (__m512i __A, __m512i __I, + __mmask32 __U, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A, + (__v32hi) __I + /* idx */ , + (__v32hi) __B, + (__mmask32) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_epi16 (__mmask32 __U, __m512i __A, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varhi512_maskz ((__v32hi) __I + /* idx */ , + (__v32hi) __A, + (__v32hi) __B, + (__mmask32) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_avg_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_avg_epu8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v64qu) __A + (__v64qu) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v64qu) __A - (__v64qu) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_avg_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_avg_epu16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_subs_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_subs_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_subs_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_subs_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_subs_epu8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_subs_epu8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_adds_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_adds_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_adds_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_adds_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_adds_epu8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_adds_epu8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v32hu) __A - (__v32hu) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_subs_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_subs_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_subs_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_subs_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_subs_epu16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_subs_epu16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v32hu) __A + (__v32hu) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_adds_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_adds_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_adds_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_adds_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_adds_epu16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srl_epi16 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srl_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srl_epi16 (__mmask32 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_packs_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sll_epi16 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sll_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m128i __B) +{ + return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sll_epi16 (__mmask32 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maddubs_epi16 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_maddubs_epi16 (__m512i __W, __mmask32 __U, __m512i __X, + __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_maddubs_epi16 (__mmask32 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_madd_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_madd_epi16 (__m512i __W, __mmask16 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_madd_epi16 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epu8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __A, + (__v64qi) __B, 0, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epi8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_pcmpeqb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epu8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __A, + (__v64qi) __B, 0, + __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_pcmpeqb512_mask ((__v64qi) __A, + (__v64qi) __B, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epu16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __A, + (__v32hi) __B, 0, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epi16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_pcmpeqw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epu16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __A, + (__v32hi) __B, 0, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_pcmpeqw512_mask ((__v32hi) __A, + (__v32hi) __B, + __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epu8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __A, + (__v64qi) __B, 6, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epi8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_pcmpgtb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epu8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __A, + (__v64qi) __B, 6, + __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_pcmpgtb512_mask ((__v64qi) __A, + (__v64qi) __B, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epu16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __A, + (__v32hi) __B, 6, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epi16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_pcmpgtw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epu16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __A, + (__v32hi) __B, 6, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_pcmpgtw512_mask ((__v32hi) __A, + (__v32hi) __B, + __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movepi8_mask (__m512i __A) +{ + return (__mmask64) __builtin_ia32_cvtb2mask512 ((__v64qi) __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movepi16_mask (__m512i __A) +{ + return (__mmask32) __builtin_ia32_cvtw2mask512 ((__v32hi) __A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movm_epi8 (__mmask64 __A) +{ + return (__m512i) __builtin_ia32_cvtmask2b512 (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movm_epi16 (__mmask32 __A) +{ + return (__m512i) __builtin_ia32_cvtmask2w512 (__A); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_test_epi8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ptestmb512 ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_test_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ptestmb512 ((__v64qi) __A, + (__v64qi) __B, __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_test_epi16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ptestmw512 ((__v32hi) __A, + (__v32hi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_test_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ptestmw512 ((__v32hi) __A, + (__v32hi) __B, __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_testn_epi8_mask (__m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ptestnmb512 ((__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_testn_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__mmask64) __builtin_ia32_ptestnmb512 ((__v64qi) __A, + (__v64qi) __B, __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_testn_epi16_mask (__m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ptestnmw512 ((__v32hi) __A, + (__v32hi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_testn_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__mmask32) __builtin_ia32_ptestnmw512 ((__v32hi) __A, + (__v32hi) __B, __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_epi8 (__mmask64 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epu16 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epi16 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epu8 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epi8 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epu8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epu8 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epi8 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A, + (__v64qi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epi16 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epi16 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epu16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epu16 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sra_epi16 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sra_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m128i __B) +{ + return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sra_epi16 (__mmask32 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A, + (__v8hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srav_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srav_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srav_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srlv_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srlv_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srlv_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sllv_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sllv_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sllv_epi16 (__mmask32 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A, + (__v32hi) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_packs_epi16 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_packs_epi16 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_packus_epi16 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_packus_epi16 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_packus_epi16 (__mmask64 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A, + (__v32hi) __B, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_epi8 (__m512i __A) +{ + return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_epi8 (__m512i __W, __mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_epi16 (__m512i __A) +{ + return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_epi16 (__m512i __W, __mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epu8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 4, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epu8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 1, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epu8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 5, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epu8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 2, + (__mmask64) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epu16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 4, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epu16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 1, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epu16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 5, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epu16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 2, + (__mmask32) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epi8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 4, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epi8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 1, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epi8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 5, + (__mmask64) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epi8_mask (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 2, + (__mmask64) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epi16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 4, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epi16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 1, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epi16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 5, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epi16_mask (__mmask32 __M, __m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 2, + (__mmask32) __M); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epu8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 4, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epu8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 1, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epu8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 5, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epu8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 2, + (__mmask64) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epu16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 4, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epu16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 1, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epu16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 5, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epu16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 2, + (__mmask32) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epi8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 4, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epi8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 1, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epi8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 5, + (__mmask64) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epi8_mask (__m512i __X, __m512i __Y) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, 2, + (__mmask64) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epi16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 4, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epi16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 1, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epi16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 5, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epi16_mask (__m512i __X, __m512i __Y) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, 2, + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_packs_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_packs_epi32 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_packs_epi32 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) __W, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_packus_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_packus_epi32 (__mmask32 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_packus_epi32 (__m512i __W, __mmask32 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A, + (__v16si) __B, + (__v32hi) __W, + __M); +} + +#ifdef __OPTIMIZE__ +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftli_mask64 (__mmask64 __A, unsigned int __B) +{ + return (__mmask64) __builtin_ia32_kshiftlidi ((__mmask64) __A, + (__mmask8) __B); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftri_mask64 (__mmask64 __A, unsigned int __B) +{ + return (__mmask64) __builtin_ia32_kshiftridi ((__mmask64) __A, + (__mmask8) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_alignr_epi8 (__m512i __A, __m512i __B, const int __N) +{ + return (__m512i) __builtin_ia32_palignr512 ((__v8di) __A, + (__v8di) __B, __N * 8); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_alignr_epi8 (__m512i __W, __mmask64 __U, __m512i __A, + __m512i __B, const int __N) +{ + return (__m512i) __builtin_ia32_palignr512_mask ((__v8di) __A, + (__v8di) __B, + __N * 8, + (__v8di) __W, + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_alignr_epi8 (__mmask64 __U, __m512i __A, __m512i __B, + const int __N) +{ + return (__m512i) __builtin_ia32_palignr512_mask ((__v8di) __A, + (__v8di) __B, + __N * 8, + (__v8di) + _mm512_setzero_si512 (), + (__mmask64) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dbsad_epu8 (__m512i __A, __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi) __A, + (__v64qi) __B, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dbsad_epu8 (__m512i __W, __mmask32 __U, __m512i __A, + __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi) __A, + (__v64qi) __B, + __imm, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dbsad_epu8 (__mmask32 __U, __m512i __A, __m512i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi) __A, + (__v64qi) __B, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srli_epi16 (__m512i __A, const unsigned int __imm) +{ + return (__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi) __A, __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srli_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + const unsigned int __imm) +{ + return (__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi) __A, __imm, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srli_epi16 (__mmask32 __U, __m512i __A, const int __imm) +{ + return (__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi) __A, __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_slli_epi16 (__m512i __A, const unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllwi512_mask ((__v32hi) __A, __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_slli_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + const unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllwi512_mask ((__v32hi) __A, __B, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_slli_epi16 (__mmask32 __U, __m512i __A, const unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllwi512_mask ((__v32hi) __A, __B, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shufflehi_epi16 (__m512i __A, const int __imm) +{ + return (__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi) __A, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shufflehi_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + const int __imm) +{ + return (__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi) __A, + __imm, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shufflehi_epi16 (__mmask32 __U, __m512i __A, + const int __imm) +{ + return (__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi) __A, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shufflelo_epi16 (__m512i __A, const int __imm) +{ + return (__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi) __A, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shufflelo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + const int __imm) +{ + return (__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi) __A, + __imm, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shufflelo_epi16 (__mmask32 __U, __m512i __A, + const int __imm) +{ + return (__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi) __A, + __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srai_epi16 (__m512i __A, const unsigned int __imm) +{ + return (__m512i) __builtin_ia32_psrawi512_mask ((__v32hi) __A, __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srai_epi16 (__m512i __W, __mmask32 __U, __m512i __A, + const unsigned int __imm) +{ + return (__m512i) __builtin_ia32_psrawi512_mask ((__v32hi) __A, __imm, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srai_epi16 (__mmask32 __U, __m512i __A, const unsigned int __imm) +{ + return (__m512i) __builtin_ia32_psrawi512_mask ((__v32hi) __A, __imm, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_epi16 (__mmask32 __U, __m512i __A, __m512i __W) +{ + return (__m512i) __builtin_ia32_blendmw_512_mask ((__v32hi) __A, + (__v32hi) __W, + (__mmask32) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_epi8 (__mmask64 __U, __m512i __A, __m512i __W) +{ + return (__m512i) __builtin_ia32_blendmb_512_mask ((__v64qi) __A, + (__v64qi) __W, + (__mmask64) __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epi16_mask (__mmask32 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, __P, + (__mmask32) __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epi16_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, __P, + (__mmask32) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epi8_mask (__mmask64 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, __P, + (__mmask64) __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epi8_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, __P, + (__mmask64) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epu16_mask (__mmask32 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, __P, + (__mmask32) __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epu16_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi) __X, + (__v32hi) __Y, __P, + (__mmask32) -1); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epu8_mask (__mmask64 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, __P, + (__mmask64) __U); +} + +extern __inline __mmask64 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epu8_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi) __X, + (__v64qi) __Y, __P, + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_bslli_epi128 (__m512i __A, const int __N) +{ + return (__m512i) __builtin_ia32_pslldq512 (__A, __N * 8); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_bsrli_epi128 (__m512i __A, const int __N) +{ + return (__m512i) __builtin_ia32_psrldq512 (__A, __N * 8); +} + +#else +#define _kshiftli_mask64(X, Y) \ + ((__mmask64) __builtin_ia32_kshiftlidi ((__mmask64)(X), (__mmask8)(Y))) + +#define _kshiftri_mask64(X, Y) \ + ((__mmask64) __builtin_ia32_kshiftridi ((__mmask64)(X), (__mmask8)(Y))) + +#define _mm512_alignr_epi8(X, Y, N) \ + ((__m512i) __builtin_ia32_palignr512 ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), \ + (int)((N) * 8))) + +#define _mm512_mask_alignr_epi8(W, U, X, Y, N) \ + ((__m512i) __builtin_ia32_palignr512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)((N) * 8), \ + (__v8di)(__m512i)(W), (__mmask64)(U))) + +#define _mm512_maskz_alignr_epi8(U, X, Y, N) \ + ((__m512i) __builtin_ia32_palignr512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)((N) * 8), \ + (__v8di)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask64)(U))) + +#define _mm512_dbsad_epu8(X, Y, C) \ + ((__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi)(__m512i) (X), \ + (__v64qi)(__m512i) (Y), (int) (C), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1)) + +#define _mm512_mask_dbsad_epu8(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi)(__m512i) (X), \ + (__v64qi)(__m512i) (Y), (int) (C), \ + (__v32hi)(__m512i)(W), \ + (__mmask32)(U))) + +#define _mm512_maskz_dbsad_epu8(U, X, Y, C) \ + ((__m512i) __builtin_ia32_dbpsadbw512_mask ((__v64qi)(__m512i) (X), \ + (__v64qi)(__m512i) (Y), (int) (C), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)(U))) + +#define _mm512_srli_epi16(A, B) \ + ((__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi)(__m512i)(A), \ + (unsigned int)(B), (__v32hi)_mm512_setzero_si512 (), (__mmask32)-1)) + +#define _mm512_mask_srli_epi16(W, U, A, B) \ + ((__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi)(__m512i)(A), \ + (unsigned int)(B), (__v32hi)(__m512i)(W), (__mmask32)(U))) + +#define _mm512_maskz_srli_epi16(U, A, B) \ + ((__m512i) __builtin_ia32_psrlwi512_mask ((__v32hi)(__m512i)(A), \ + (int)(B), (__v32hi)_mm512_setzero_si512 (), (__mmask32)(U))) + +#define _mm512_slli_epi16(X, C) \ + ((__m512i)__builtin_ia32_psllwi512_mask ((__v32hi)(__m512i)(X), \ + (unsigned int)(C), \ + (__v32hi)(__m512i)_mm512_setzero_si512 (), \ + (__mmask32)-1)) + +#define _mm512_mask_slli_epi16(W, U, X, C) \ + ((__m512i)__builtin_ia32_psllwi512_mask ((__v32hi)(__m512i)(X), \ + (unsigned int)(C), \ + (__v32hi)(__m512i)(W), \ + (__mmask32)(U))) + +#define _mm512_maskz_slli_epi16(U, X, C) \ + ((__m512i)__builtin_ia32_psllwi512_mask ((__v32hi)(__m512i)(X), \ + (unsigned int)(C), \ + (__v32hi)(__m512i)_mm512_setzero_si512 (), \ + (__mmask32)(U))) + +#define _mm512_shufflehi_epi16(A, B) \ + ((__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1)) + +#define _mm512_mask_shufflehi_epi16(W, U, A, B) \ + ((__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i)(W), \ + (__mmask32)(U))) + +#define _mm512_maskz_shufflehi_epi16(U, A, B) \ + ((__m512i) __builtin_ia32_pshufhw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)(U))) + +#define _mm512_shufflelo_epi16(A, B) \ + ((__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1)) + +#define _mm512_mask_shufflelo_epi16(W, U, A, B) \ + ((__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i)(W), \ + (__mmask32)(U))) + +#define _mm512_maskz_shufflelo_epi16(U, A, B) \ + ((__m512i) __builtin_ia32_pshuflw512_mask ((__v32hi)(__m512i)(A), (int)(B), \ + (__v32hi)(__m512i) \ + _mm512_setzero_si512 (), \ + (__mmask32)(U))) + +#define _mm512_srai_epi16(A, B) \ + ((__m512i) __builtin_ia32_psrawi512_mask ((__v32hi)(__m512i)(A), \ + (unsigned int)(B), (__v32hi)_mm512_setzero_si512 (), (__mmask32)-1)) + +#define _mm512_mask_srai_epi16(W, U, A, B) \ + ((__m512i) __builtin_ia32_psrawi512_mask ((__v32hi)(__m512i)(A), \ + (unsigned int)(B), (__v32hi)(__m512i)(W), (__mmask32)(U))) + +#define _mm512_maskz_srai_epi16(U, A, B) \ + ((__m512i) __builtin_ia32_psrawi512_mask ((__v32hi)(__m512i)(A), \ + (unsigned int)(B), (__v32hi)_mm512_setzero_si512 (), (__mmask32)(U))) + +#define _mm512_mask_blend_epi16(__U, __A, __W) \ + ((__m512i) __builtin_ia32_blendmw_512_mask ((__v32hi) (__A), \ + (__v32hi) (__W), \ + (__mmask32) (__U))) + +#define _mm512_mask_blend_epi8(__U, __A, __W) \ + ((__m512i) __builtin_ia32_blendmb_512_mask ((__v64qi) (__A), \ + (__v64qi) (__W), \ + (__mmask64) (__U))) + +#define _mm512_cmp_epi16_mask(X, Y, P) \ + ((__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi)(__m512i)(X), \ + (__v32hi)(__m512i)(Y), (int)(P),\ + (__mmask32)(-1))) + +#define _mm512_cmp_epi8_mask(X, Y, P) \ + ((__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi)(__m512i)(X), \ + (__v64qi)(__m512i)(Y), (int)(P),\ + (__mmask64)(-1))) + +#define _mm512_cmp_epu16_mask(X, Y, P) \ + ((__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi)(__m512i)(X), \ + (__v32hi)(__m512i)(Y), (int)(P),\ + (__mmask32)(-1))) + +#define _mm512_cmp_epu8_mask(X, Y, P) \ + ((__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi)(__m512i)(X), \ + (__v64qi)(__m512i)(Y), (int)(P),\ + (__mmask64)(-1))) + +#define _mm512_mask_cmp_epi16_mask(M, X, Y, P) \ + ((__mmask32) __builtin_ia32_cmpw512_mask ((__v32hi)(__m512i)(X), \ + (__v32hi)(__m512i)(Y), (int)(P),\ + (__mmask32)(M))) + +#define _mm512_mask_cmp_epi8_mask(M, X, Y, P) \ + ((__mmask64) __builtin_ia32_cmpb512_mask ((__v64qi)(__m512i)(X), \ + (__v64qi)(__m512i)(Y), (int)(P),\ + (__mmask64)(M))) + +#define _mm512_mask_cmp_epu16_mask(M, X, Y, P) \ + ((__mmask32) __builtin_ia32_ucmpw512_mask ((__v32hi)(__m512i)(X), \ + (__v32hi)(__m512i)(Y), (int)(P),\ + (__mmask32)(M))) + +#define _mm512_mask_cmp_epu8_mask(M, X, Y, P) \ + ((__mmask64) __builtin_ia32_ucmpb512_mask ((__v64qi)(__m512i)(X), \ + (__v64qi)(__m512i)(Y), (int)(P),\ + (__mmask64)(M))) + +#define _mm512_bslli_epi128(A, N) \ + ((__m512i)__builtin_ia32_pslldq512 ((__m512i)(A), (int)(N) * 8)) + +#define _mm512_bsrli_epi128(A, N) \ + ((__m512i)__builtin_ia32_psrldq512 ((__m512i)(A), (int)(N) * 8)) + +#endif + +#ifdef __DISABLE_AVX512BW_512__ +#undef __DISABLE_AVX512BW_512__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512BW_512__ */ + +#endif /* _AVX512BWINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512cdintrin.h b/template/sysroot/include/avx512cdintrin.h new file mode 100644 index 0000000..24ae280 --- /dev/null +++ b/template/sysroot/include/avx512cdintrin.h @@ -0,0 +1,184 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512CDINTRIN_H_INCLUDED +#define _AVX512CDINTRIN_H_INCLUDED + +#ifndef __AVX512CD__ +#pragma GCC push_options +#pragma GCC target("avx512cd,evex512") +#define __DISABLE_AVX512CD__ +#endif /* __AVX512CD__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef long long __v8di __attribute__ ((__vector_size__ (64))); +typedef int __v16si __attribute__ ((__vector_size__ (64))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +typedef unsigned char __mmask8; +typedef unsigned short __mmask16; + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_conflict_epi32 (__m512i __A) +{ + return (__m512i) + __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A, + (__v16si) _mm512_setzero_si512 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_conflict_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_conflict_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) + __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A, + (__v16si) _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_conflict_epi64 (__m512i __A) +{ + return (__m512i) + __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A, + (__v8di) _mm512_setzero_si512 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_conflict_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_conflict_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) + __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A, + (__v8di) _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_lzcnt_epi64 (__m512i __A) +{ + return (__m512i) + __builtin_ia32_vplzcntq_512_mask ((__v8di) __A, + (__v8di) _mm512_setzero_si512 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_lzcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) + __builtin_ia32_vplzcntq_512_mask ((__v8di) __A, + (__v8di) _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_lzcnt_epi32 (__m512i __A) +{ + return (__m512i) + __builtin_ia32_vplzcntd_512_mask ((__v16si) __A, + (__v16si) _mm512_setzero_si512 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_lzcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_lzcnt_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) + __builtin_ia32_vplzcntd_512_mask ((__v16si) __A, + (__v16si) _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastmb_epi64 (__mmask8 __A) +{ + return (__m512i) __builtin_ia32_broadcastmb512 (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastmw_epi32 (__mmask16 __A) +{ + return (__m512i) __builtin_ia32_broadcastmw512 (__A); +} + +#ifdef __DISABLE_AVX512CD__ +#undef __DISABLE_AVX512CD__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512CD__ */ + +#endif /* _AVX512CDINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512dqintrin.h b/template/sysroot/include/avx512dqintrin.h new file mode 100644 index 0000000..d9890c6 --- /dev/null +++ b/template/sysroot/include/avx512dqintrin.h @@ -0,0 +1,2905 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512DQINTRIN_H_INCLUDED +#define _AVX512DQINTRIN_H_INCLUDED + +#if !defined (__AVX512DQ__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512dq,no-evex512") +#define __DISABLE_AVX512DQ__ +#endif /* __AVX512DQ__ */ + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktest_mask8_u8 (__mmask8 __A, __mmask8 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_ktestcqi (__A, __B); + return (unsigned char) __builtin_ia32_ktestzqi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestz_mask8_u8 (__mmask8 __A, __mmask8 __B) +{ + return (unsigned char) __builtin_ia32_ktestzqi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestc_mask8_u8 (__mmask8 __A, __mmask8 __B) +{ + return (unsigned char) __builtin_ia32_ktestcqi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktest_mask16_u8 (__mmask16 __A, __mmask16 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_ktestchi (__A, __B); + return (unsigned char) __builtin_ia32_ktestzhi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestz_mask16_u8 (__mmask16 __A, __mmask16 __B) +{ + return (unsigned char) __builtin_ia32_ktestzhi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_ktestc_mask16_u8 (__mmask16 __A, __mmask16 __B) +{ + return (unsigned char) __builtin_ia32_ktestchi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortest_mask8_u8 (__mmask8 __A, __mmask8 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_kortestcqi (__A, __B); + return (unsigned char) __builtin_ia32_kortestzqi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestz_mask8_u8 (__mmask8 __A, __mmask8 __B) +{ + return (unsigned char) __builtin_ia32_kortestzqi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestc_mask8_u8 (__mmask8 __A, __mmask8 __B) +{ + return (unsigned char) __builtin_ia32_kortestcqi (__A, __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kadd_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_kaddqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kadd_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kaddhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtmask8_u32 (__mmask8 __A) +{ + return (unsigned int) __builtin_ia32_kmovb ((__mmask8 ) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtu32_mask8 (unsigned int __A) +{ + return (__mmask8) __builtin_ia32_kmovb ((__mmask8) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_load_mask8 (__mmask8 *__A) +{ + return (__mmask8) __builtin_ia32_kmovb (*(__mmask8 *) __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_store_mask8 (__mmask8 *__A, __mmask8 __B) +{ + *(__mmask8 *) __A = __builtin_ia32_kmovb (__B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_knot_mask8 (__mmask8 __A) +{ + return (__mmask8) __builtin_ia32_knotqi ((__mmask8) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kor_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_korqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxnor_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_kxnorqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxor_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_kxorqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kand_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_kandqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kandn_mask8 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask8) __builtin_ia32_kandnqi ((__mmask8) __A, (__mmask8) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftli_mask8 (__mmask8 __A, unsigned int __B) +{ + return (__mmask8) __builtin_ia32_kshiftliqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftri_mask8 (__mmask8 __A, unsigned int __B) +{ + return (__mmask8) __builtin_ia32_kshiftriqi ((__mmask8) __A, (__mmask8) __B); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_sd (__m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_reducesd_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_round_sd (__m128d __A, __m128d __B, int __C, const int __R) +{ + return (__m128d) __builtin_ia32_reducesd_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_reducesd_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, int __C, const int __R) +{ + return (__m128d) __builtin_ia32_reducesd_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) __W, + __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_sd (__mmask8 __U, __m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_reducesd_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + int __C, const int __R) +{ + return (__m128d) __builtin_ia32_reducesd_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_ss (__m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_reducess_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_round_ss (__m128 __A, __m128 __B, int __C, const int __R) +{ + return (__m128) __builtin_ia32_reducess_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_reducess_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, int __C, const int __R) +{ + return (__m128) __builtin_ia32_reducess_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) __W, + __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_ss (__mmask8 __U, __m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_reducess_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + int __C, const int __R) +{ + return (__m128) __builtin_ia32_reducess_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_sd (__m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_sd (__mmask8 __U, __m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_ss (__m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_ss (__mmask8 __U, __m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_round_sd (__m128d __A, __m128d __B, int __C, const int __R) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + int __C, const int __R) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __C, + const int __R) +{ + return (__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_round_ss (__m128 __A, __m128 __B, int __C, const int __R) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + int __C, const int __R) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __C, + const int __R) +{ + return (__m128) __builtin_ia32_rangess128_mask_round ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_ss_mask (__m128 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) __A, __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_sd_mask (__m128d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) __A, __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fpclass_ss_mask (__mmask8 __U, __m128 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) __A, __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fpclass_sd_mask (__mmask8 __U, __m128d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) __A, __imm, __U); +} + +#else +#define _kshiftli_mask8(X, Y) \ + ((__mmask8) __builtin_ia32_kshiftliqi ((__mmask8)(X), (__mmask8)(Y))) + +#define _kshiftri_mask8(X, Y) \ + ((__mmask8) __builtin_ia32_kshiftriqi ((__mmask8)(X), (__mmask8)(Y))) + +#define _mm_range_sd(A, B, C) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) -1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_range_sd(W, U, A, B, C) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df)(__m128d)(W), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_range_sd(U, A, B, C) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_range_ss(A, B, C) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) -1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_range_ss(W, U, A, B, C) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf)(__m128)(W), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_range_ss(U, A, B, C) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_range_round_sd(A, B, C, R) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) -1, (R))) + +#define _mm_mask_range_round_sd(W, U, A, B, C, R) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df)(__m128d)(W), \ + (__mmask8)(U), (R))) + +#define _mm_maskz_range_round_sd(U, A, B, C, R) \ + ((__m128d) __builtin_ia32_rangesd128_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(U), (R))) + +#define _mm_range_round_ss(A, B, C, R) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) -1, (R))) + +#define _mm_mask_range_round_ss(W, U, A, B, C, R) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf)(__m128)(W), \ + (__mmask8)(U), (R))) + +#define _mm_maskz_range_round_ss(U, A, B, C, R) \ + ((__m128) __builtin_ia32_rangess128_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(U), (R))) + +#define _mm_fpclass_ss_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) (__m128) (X), \ + (int) (C), (__mmask8) (-1))) \ + +#define _mm_fpclass_sd_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \ + (int) (C), (__mmask8) (-1))) \ + +#define _mm_mask_fpclass_ss_mask(U, X, C) \ + ((__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) (__m128) (X), \ + (int) (C), (__mmask8) (U))) + +#define _mm_mask_fpclass_sd_mask(U, X, C) \ + ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \ + (int) (C), (__mmask8) (U))) +#define _mm_reduce_sd(A, B, C) \ + ((__m128d) __builtin_ia32_reducesd_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)-1)) + +#define _mm_mask_reduce_sd(W, U, A, B, C) \ + ((__m128d) __builtin_ia32_reducesd_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df)(__m128d)(W), (__mmask8)(U))) + +#define _mm_maskz_reduce_sd(U, A, B, C) \ + ((__m128d) __builtin_ia32_reducesd_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(U))) + +#define _mm_reduce_round_sd(A, B, C, R) \ + ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(-1), (int)(R))) + +#define _mm_mask_reduce_round_sd(W, U, A, B, C, R) \ + ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df)(__m128d)(W), \ + (__mmask8)(U), (int)(R))) + +#define _mm_maskz_reduce_round_sd(U, A, B, C, R) \ + ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(U), (int)(R))) + +#define _mm_reduce_ss(A, B, C) \ + ((__m128) __builtin_ia32_reducess_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm_mask_reduce_ss(W, U, A, B, C) \ + ((__m128) __builtin_ia32_reducess_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf)(__m128)(W), (__mmask8)(U))) + +#define _mm_maskz_reduce_ss(U, A, B, C) \ + ((__m128) __builtin_ia32_reducess_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm_reduce_round_ss(A, B, C, R) \ + ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(-1), (int)(R))) + +#define _mm_mask_reduce_round_ss(W, U, A, B, C, R) \ + ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf)(__m128)(W), \ + (__mmask8)(U), (int)(R))) + +#define _mm_maskz_reduce_round_ss(U, A, B, C, R) \ + ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(U), (int)(R))) + +#endif + +#ifdef __DISABLE_AVX512DQ__ +#undef __DISABLE_AVX512DQ__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512DQ__ */ + +#if !defined (__AVX512DQ__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512dq,evex512") +#define __DISABLE_AVX512DQ_512__ +#endif /* __AVX512DQ_512__ */ + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_f64x2 (__m128d __A) +{ + return (__m512d) + __builtin_ia32_broadcastf64x2_512_mask ((__v2df) __A, + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_f64x2 (__m512d __O, __mmask8 __M, __m128d __A) +{ + return (__m512d) __builtin_ia32_broadcastf64x2_512_mask ((__v2df) + __A, + (__v8df) + __O, __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A) +{ + return (__m512d) __builtin_ia32_broadcastf64x2_512_mask ((__v2df) + __A, + (__v8df) + _mm512_setzero_ps (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_i64x2 (__m128i __A) +{ + return (__m512i) + __builtin_ia32_broadcasti64x2_512_mask ((__v2di) __A, + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_i64x2 (__m512i __O, __mmask8 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti64x2_512_mask ((__v2di) + __A, + (__v8di) + __O, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti64x2_512_mask ((__v2di) + __A, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_f32x2 (__m128 __A) +{ + return (__m512) + __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A, + (__v16sf)_mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_f32x2 (__m512 __O, __mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A, + (__v16sf) + __O, __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_f32x2 (__mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A, + (__v16sf) + _mm512_setzero_ps (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_i32x2 (__m128i __A) +{ + return (__m512i) + __builtin_ia32_broadcasti32x2_512_mask ((__v4si) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_i32x2 (__m512i __O, __mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x2_512_mask ((__v4si) + __A, + (__v16si) + __O, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_i32x2 (__mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x2_512_mask ((__v4si) + __A, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_f32x8 (__m256 __A) +{ + return (__m512) + __builtin_ia32_broadcastf32x8_512_mask ((__v8sf) __A, + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_f32x8 (__m512 __O, __mmask16 __M, __m256 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x8_512_mask ((__v8sf) __A, + (__v16sf)__O, + __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_f32x8 (__mmask16 __M, __m256 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x8_512_mask ((__v8sf) __A, + (__v16sf) + _mm512_setzero_ps (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_i32x8 (__m256i __A) +{ + return (__m512i) + __builtin_ia32_broadcasti32x8_512_mask ((__v8si) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_i32x8 (__m512i __O, __mmask16 __M, __m256i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x8_512_mask ((__v8si) + __A, + (__v16si)__O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_i32x8 (__mmask16 __M, __m256i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x8_512_mask ((__v8si) + __A, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mullo_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A * (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mullo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_xor_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_xor_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B) +{ + return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_xor_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_xor_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_xor_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_xor_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_or_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_or_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_or_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_or_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_or_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_or_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_and_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_and_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B) +{ + return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_and_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_and_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_and_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_and_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_andnot_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_andnot_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B) +{ + return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_andnot_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_andnot_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_andnot_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B) +{ + return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_andnot_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movepi32_mask (__m512i __A) +{ + return (__mmask16) __builtin_ia32_cvtd2mask512 ((__v16si) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movepi64_mask (__m512i __A) +{ + return (__mmask8) __builtin_ia32_cvtq2mask512 ((__v8di) __A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movm_epi32 (__mmask16 __A) +{ + return (__m512i) __builtin_ia32_cvtmask2d512 (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movm_epi64 (__mmask8 __A) +{ + return (__m512i) __builtin_ia32_cvtmask2q512 (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttpd_epi64 (__m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttpd_epi64 (__mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttpd_epu64 (__m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttpd_epu64 (__mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttps_epi64 (__m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttps_epi64 (__mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttps_epu64 (__m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttps_epu64 (__mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_epi64 (__m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_epi64 (__mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_epu64 (__m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_epu64 (__mmask8 __U, __m512d __A) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_epi64 (__m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_epi64 (__mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_epu64 (__m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_epu64 (__mmask8 __U, __m256 __A) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_ps (__m512i __A) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_ps (__m256 __W, __mmask8 __U, __m512i __A) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_ps (__mmask8 __U, __m512i __A) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu64_ps (__m512i __A) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu64_ps (__m256 __W, __mmask8 __U, __m512i __A) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu64_ps (__mmask8 __U, __m512i __A) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_pd (__m512i __A) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_pd (__m512d __W, __mmask8 __U, __m512i __A) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_pd (__mmask8 __U, __m512i __A) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu64_pd (__m512i __A) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu64_pd (__m512d __W, __mmask8 __U, __m512i __A) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu64_pd (__mmask8 __U, __m512i __A) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_range_pd (__m512d __A, __m512d __B, int __C) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_range_pd (__m512d __W, __mmask8 __U, + __m512d __A, __m512d __B, int __C) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_range_pd (__mmask8 __U, __m512d __A, __m512d __B, int __C) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_range_ps (__m512 __A, __m512 __B, int __C) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_range_ps (__m512 __W, __mmask16 __U, + __m512 __A, __m512 __B, int __C) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_range_ps (__mmask16 __U, __m512 __A, __m512 __B, int __C) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundpd_epi64 (__m512d __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundpd_epi64 (__mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundpd_epu64 (__m512d __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundpd_epu64 (__mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundps_epi64 (__m256 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundps_epi64 (__m512i __W, __mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundps_epi64 (__mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundps_epu64 (__m256 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundps_epu64 (__m512i __W, __mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundps_epu64 (__mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_epi64 (__m512d __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_epi64 (__mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_epu64 (__m512d __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_epu64 (__mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_epi64 (__m256 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_epi64 (__m512i __W, __mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_epi64 (__mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_epu64 (__m256 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_epu64 (__m512i __W, __mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_epu64 (__mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi64_ps (__m512i __A, const int __R) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) -1, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi64_ps (__m256 __W, __mmask8 __U, __m512i __A, + const int __R) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi64_ps (__mmask8 __U, __m512i __A, + const int __R) +{ + return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu64_ps (__m512i __A, const int __R) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) -1, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu64_ps (__m256 __W, __mmask8 __U, __m512i __A, + const int __R) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu64_ps (__mmask8 __U, __m512i __A, + const int __R) +{ + return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi64_pd (__m512i __A, const int __R) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi64_pd (__m512d __W, __mmask8 __U, __m512i __A, + const int __R) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi64_pd (__mmask8 __U, __m512i __A, + const int __R) +{ + return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu64_pd (__m512i __A, const int __R) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu64_pd (__m512d __W, __mmask8 __U, __m512i __A, + const int __R) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu64_pd (__mmask8 __U, __m512i __A, + const int __R) +{ + return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_pd (__m512d __A, int __B) +{ + return (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_round_pd (__m512d __A, int __B, const int __R) +{ + return (__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df) __A, + __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_pd (__m512d __W, __mmask8 __U, __m512d __A, int __B) +{ + return (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + int __B, const int __R) +{ + return (__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df) __A, + __B, + (__v8df) __W, + __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_pd (__mmask8 __U, __m512d __A, int __B) +{ + return (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_round_pd (__mmask8 __U, __m512d __A, int __B, + const int __R) +{ + return (__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df) __A, + __B, + (__v8df) + _mm512_setzero_pd (), + __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_ps (__m512 __A, int __B) +{ + return (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_round_ps (__m512 __A, int __B, const int __R) +{ + return (__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf) __A, + __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_ps (__m512 __W, __mmask16 __U, __m512 __A, int __B) +{ + return (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __B, + const int __R) +{ + return (__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf) __A, + __B, + (__v16sf) __W, + __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_ps (__mmask16 __U, __m512 __A, int __B) +{ + return (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_round_ps (__mmask16 __U, __m512 __A, int __B, + const int __R) +{ + return (__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf) __A, + __B, + (__v16sf) + _mm512_setzero_ps (), + __U, __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extractf32x8_ps (__m512 __A, const int __imm) +{ + return (__m256) __builtin_ia32_extractf32x8_mask ((__v16sf) __A, + __imm, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extractf32x8_ps (__m256 __W, __mmask8 __U, __m512 __A, + const int __imm) +{ + return (__m256) __builtin_ia32_extractf32x8_mask ((__v16sf) __A, + __imm, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extractf32x8_ps (__mmask8 __U, __m512 __A, + const int __imm) +{ + return (__m256) __builtin_ia32_extractf32x8_mask ((__v16sf) __A, + __imm, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extractf64x2_pd (__m512d __A, const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df) __A, + __imm, + (__v2df) + _mm_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extractf64x2_pd (__m128d __W, __mmask8 __U, __m512d __A, + const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df) __A, + __imm, + (__v2df) __W, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extractf64x2_pd (__mmask8 __U, __m512d __A, + const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df) __A, + __imm, + (__v2df) + _mm_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extracti32x8_epi32 (__m512i __A, const int __imm) +{ + return (__m256i) __builtin_ia32_extracti32x8_mask ((__v16si) __A, + __imm, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extracti32x8_epi32 (__m256i __W, __mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_extracti32x8_mask ((__v16si) __A, + __imm, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extracti32x8_epi32 (__mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_extracti32x8_mask ((__v16si) __A, + __imm, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extracti64x2_epi64 (__m512i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di) __A, + __imm, + (__v2di) + _mm_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extracti64x2_epi64 (__m128i __W, __mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di) __A, + __imm, + (__v2di) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extracti64x2_epi64 (__mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di) __A, + __imm, + (__v2di) + _mm_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_range_round_pd (__m512d __A, __m512d __B, int __C, + const int __R) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_range_round_pd (__m512d __W, __mmask8 __U, + __m512d __A, __m512d __B, int __C, + const int __R) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) __W, + (__mmask8) __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_range_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + int __C, const int __R) +{ + return (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, + (__v8df) __B, __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_range_round_ps (__m512 __A, __m512 __B, int __C, const int __R) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1, + __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_range_round_ps (__m512 __W, __mmask16 __U, + __m512 __A, __m512 __B, int __C, + const int __R) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) __W, + (__mmask16) __U, + __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_range_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + int __C, const int __R) +{ + return (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, + (__v16sf) __B, __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_inserti32x8 (__m512i __A, __m256i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x8_mask ((__v16si) __A, + (__v8si) __B, + __imm, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_inserti32x8 (__m512i __W, __mmask16 __U, __m512i __A, + __m256i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x8_mask ((__v16si) __A, + (__v8si) __B, + __imm, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_inserti32x8 (__mmask16 __U, __m512i __A, __m256i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x8_mask ((__v16si) __A, + (__v8si) __B, + __imm, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_insertf32x8 (__m512 __A, __m256 __B, const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x8_mask ((__v16sf) __A, + (__v8sf) __B, + __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_insertf32x8 (__m512 __W, __mmask16 __U, __m512 __A, + __m256 __B, const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x8_mask ((__v16sf) __A, + (__v8sf) __B, + __imm, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_insertf32x8 (__mmask16 __U, __m512 __A, __m256 __B, + const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x8_mask ((__v16sf) __A, + (__v8sf) __B, + __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_inserti64x2 (__m512i __A, __m128i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di) __A, + (__v2di) __B, + __imm, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_inserti64x2 (__m512i __W, __mmask8 __U, __m512i __A, + __m128i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di) __A, + (__v2di) __B, + __imm, + (__v8di) __W, + (__mmask8) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_inserti64x2 (__mmask8 __U, __m512i __A, __m128i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di) __A, + (__v2di) __B, + __imm, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) + __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_insertf64x2 (__m512d __A, __m128d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df) __A, + (__v2df) __B, + __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_insertf64x2 (__m512d __W, __mmask8 __U, __m512d __A, + __m128d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df) __A, + (__v2df) __B, + __imm, + (__v8df) __W, + (__mmask8) + __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_insertf64x2 (__mmask8 __U, __m512d __A, __m128d __B, + const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df) __A, + (__v2df) __B, + __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fpclass_pd_mask (__mmask8 __U, __m512d __A, + const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fpclass_pd_mask (__m512d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fpclass_ps_mask (__mmask16 __U, __m512 __A, + const int __imm) +{ + return (__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) __A, + __imm, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fpclass_ps_mask (__m512 __A, const int __imm) +{ + return (__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) __A, + __imm, + (__mmask16) -1); +} + +#else +#define _mm512_cvtt_roundpd_epi64(A, B) \ + ((__m512i)__builtin_ia32_cvttpd2qq512_mask ((A), (__v8di) \ + _mm512_setzero_si512 (), \ + -1, (B))) + +#define _mm512_mask_cvtt_roundpd_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttpd2qq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvtt_roundpd_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_cvttpd2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvtt_roundpd_epu64(A, B) \ + ((__m512i)__builtin_ia32_cvttpd2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvtt_roundpd_epu64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttpd2uqq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvtt_roundpd_epu64(U, A, B) \ + ((__m512i)__builtin_ia32_cvttpd2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvtt_roundps_epi64(A, B) \ + ((__m512i)__builtin_ia32_cvttps2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvtt_roundps_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2qq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvtt_roundps_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvtt_roundps_epu64(A, B) \ + ((__m512i)__builtin_ia32_cvttps2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvtt_roundps_epu64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2uqq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvtt_roundps_epu64(U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvt_roundpd_epi64(A, B) \ + ((__m512i)__builtin_ia32_cvtpd2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvt_roundpd_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtpd2qq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvt_roundpd_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_cvtpd2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvt_roundpd_epu64(A, B) \ + ((__m512i)__builtin_ia32_cvtpd2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvt_roundpd_epu64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtpd2uqq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvt_roundpd_epu64(U, A, B) \ + ((__m512i)__builtin_ia32_cvtpd2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvt_roundps_epi64(A, B) \ + ((__m512i)__builtin_ia32_cvtps2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvt_roundps_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2qq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvt_roundps_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2qq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvt_roundps_epu64(A, B) \ + ((__m512i)__builtin_ia32_cvtps2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), -1, (B))) + +#define _mm512_mask_cvt_roundps_epu64(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2uqq512_mask ((A), (__v8di)(W), (U), (B))) + +#define _mm512_maskz_cvt_roundps_epu64(U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2uqq512_mask ((A), (__v8di)_mm512_setzero_si512 (), (U), (B))) + +#define _mm512_cvt_roundepi64_ps(A, B) \ + ((__m256)__builtin_ia32_cvtqq2ps512_mask ((__v8di)(A), (__v8sf)_mm256_setzero_ps (), -1, (B))) + +#define _mm512_mask_cvt_roundepi64_ps(W, U, A, B) \ + ((__m256)__builtin_ia32_cvtqq2ps512_mask ((__v8di)(A), (W), (U), (B))) + +#define _mm512_maskz_cvt_roundepi64_ps(U, A, B) \ + ((__m256)__builtin_ia32_cvtqq2ps512_mask ((__v8di)(A), (__v8sf)_mm256_setzero_ps (), (U), (B))) + +#define _mm512_cvt_roundepu64_ps(A, B) \ + ((__m256)__builtin_ia32_cvtuqq2ps512_mask ((__v8di)(A), (__v8sf)_mm256_setzero_ps (), -1, (B))) + +#define _mm512_mask_cvt_roundepu64_ps(W, U, A, B) \ + ((__m256)__builtin_ia32_cvtuqq2ps512_mask ((__v8di)(A), (W), (U), (B))) + +#define _mm512_maskz_cvt_roundepu64_ps(U, A, B) \ + ((__m256)__builtin_ia32_cvtuqq2ps512_mask ((__v8di)(A), (__v8sf)_mm256_setzero_ps (), (U), (B))) + +#define _mm512_cvt_roundepi64_pd(A, B) \ + ((__m512d)__builtin_ia32_cvtqq2pd512_mask ((__v8di)(A), (__v8df)_mm512_setzero_pd (), -1, (B))) + +#define _mm512_mask_cvt_roundepi64_pd(W, U, A, B) \ + ((__m512d)__builtin_ia32_cvtqq2pd512_mask ((__v8di)(A), (W), (U), (B))) + +#define _mm512_maskz_cvt_roundepi64_pd(U, A, B) \ + ((__m512d)__builtin_ia32_cvtqq2pd512_mask ((__v8di)(A), (__v8df)_mm512_setzero_pd (), (U), (B))) + +#define _mm512_cvt_roundepu64_pd(A, B) \ + ((__m512d)__builtin_ia32_cvtuqq2pd512_mask ((__v8di)(A), (__v8df)_mm512_setzero_pd (), -1, (B))) + +#define _mm512_mask_cvt_roundepu64_pd(W, U, A, B) \ + ((__m512d)__builtin_ia32_cvtuqq2pd512_mask ((__v8di)(A), (W), (U), (B))) + +#define _mm512_maskz_cvt_roundepu64_pd(U, A, B) \ + ((__m512d)__builtin_ia32_cvtuqq2pd512_mask ((__v8di)(A), (__v8df)_mm512_setzero_pd (), (U), (B))) + +#define _mm512_reduce_pd(A, B) \ + ((__m512d) __builtin_ia32_reducepd512_mask ((__v8df)(__m512d)(A), \ + (int)(B), (__v8df)_mm512_setzero_pd (), (__mmask8)-1)) + +#define _mm512_reduce_round_pd(A, B, R) \ + ((__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df)(__m512d)(A),\ + (int)(B), (__v8df)_mm512_setzero_pd (), (__mmask8)-1, (R))) + +#define _mm512_mask_reduce_pd(W, U, A, B) \ + ((__m512d) __builtin_ia32_reducepd512_mask ((__v8df)(__m512d)(A), \ + (int)(B), (__v8df)(__m512d)(W), (__mmask8)(U))) + +#define _mm512_mask_reduce_round_pd(W, U, A, B, R) \ + ((__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df)(__m512d)(A),\ + (int)(B), (__v8df)(__m512d)(W), (U), (R))) + +#define _mm512_maskz_reduce_pd(U, A, B) \ + ((__m512d) __builtin_ia32_reducepd512_mask ((__v8df)(__m512d)(A), \ + (int)(B), (__v8df)_mm512_setzero_pd (), (__mmask8)(U))) + +#define _mm512_maskz_reduce_round_pd(U, A, B, R) \ + ((__m512d) __builtin_ia32_reducepd512_mask_round ((__v8df)(__m512d)(A),\ + (int)(B), (__v8df)_mm512_setzero_pd (), (U), (R))) + +#define _mm512_reduce_ps(A, B) \ + ((__m512) __builtin_ia32_reduceps512_mask ((__v16sf)(__m512)(A), \ + (int)(B), (__v16sf)_mm512_setzero_ps (), (__mmask16)-1)) + +#define _mm512_reduce_round_ps(A, B, R) \ + ((__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf)(__m512)(A),\ + (int)(B), (__v16sf)_mm512_setzero_ps (), (__mmask16)-1, (R))) + +#define _mm512_mask_reduce_ps(W, U, A, B) \ + ((__m512) __builtin_ia32_reduceps512_mask ((__v16sf)(__m512)(A), \ + (int)(B), (__v16sf)(__m512)(W), (__mmask16)(U))) + +#define _mm512_mask_reduce_round_ps(W, U, A, B, R) \ + ((__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf)(__m512)(A),\ + (int)(B), (__v16sf)(__m512)(W), (U), (R))) + +#define _mm512_maskz_reduce_ps(U, A, B) \ + ((__m512) __builtin_ia32_reduceps512_mask ((__v16sf)(__m512)(A), \ + (int)(B), (__v16sf)_mm512_setzero_ps (), (__mmask16)(U))) + +#define _mm512_maskz_reduce_round_ps(U, A, B, R) \ + ((__m512) __builtin_ia32_reduceps512_mask_round ((__v16sf)(__m512)(A),\ + (int)(B), (__v16sf)_mm512_setzero_ps (), (__mmask16)(U), (R))) + +#define _mm512_extractf32x8_ps(X, C) \ + ((__m256) __builtin_ia32_extractf32x8_mask ((__v16sf)(__m512) (X), \ + (int) (C), (__v8sf)(__m256) _mm256_setzero_ps (), (__mmask8)-1)) + +#define _mm512_mask_extractf32x8_ps(W, U, X, C) \ + ((__m256) __builtin_ia32_extractf32x8_mask ((__v16sf)(__m512) (X), \ + (int) (C), (__v8sf)(__m256) (W), (__mmask8) (U))) + +#define _mm512_maskz_extractf32x8_ps(U, X, C) \ + ((__m256) __builtin_ia32_extractf32x8_mask ((__v16sf)(__m512) (X), \ + (int) (C), (__v8sf)(__m256) _mm256_setzero_ps (), (__mmask8) (U))) + +#define _mm512_extractf64x2_pd(X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df)(__m512d) (X),\ + (int) (C), (__v2df)(__m128d) _mm_setzero_pd (), (__mmask8)-1)) + +#define _mm512_mask_extractf64x2_pd(W, U, X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df)(__m512d) (X),\ + (int) (C), (__v2df)(__m128d) (W), (__mmask8) (U))) + +#define _mm512_maskz_extractf64x2_pd(U, X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_512_mask ((__v8df)(__m512d) (X),\ + (int) (C), (__v2df)(__m128d) _mm_setzero_pd (), (__mmask8) (U))) + +#define _mm512_extracti32x8_epi32(X, C) \ + ((__m256i) __builtin_ia32_extracti32x8_mask ((__v16si)(__m512i) (X), \ + (int) (C), (__v8si)(__m256i) _mm256_setzero_si256 (), (__mmask8)-1)) + +#define _mm512_mask_extracti32x8_epi32(W, U, X, C) \ + ((__m256i) __builtin_ia32_extracti32x8_mask ((__v16si)(__m512i) (X), \ + (int) (C), (__v8si)(__m256i) (W), (__mmask8) (U))) + +#define _mm512_maskz_extracti32x8_epi32(U, X, C) \ + ((__m256i) __builtin_ia32_extracti32x8_mask ((__v16si)(__m512i) (X), \ + (int) (C), (__v8si)(__m256i) _mm256_setzero_si256 (), (__mmask8) (U))) + +#define _mm512_extracti64x2_epi64(X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di)(__m512i) (X),\ + (int) (C), (__v2di)(__m128i) _mm_setzero_si128 (), (__mmask8)-1)) + +#define _mm512_mask_extracti64x2_epi64(W, U, X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di)(__m512i) (X),\ + (int) (C), (__v2di)(__m128i) (W), (__mmask8) (U))) + +#define _mm512_maskz_extracti64x2_epi64(U, X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_512_mask ((__v8di)(__m512i) (X),\ + (int) (C), (__v2di)(__m128i) _mm_setzero_si128 (), (__mmask8) (U))) + +#define _mm512_range_pd(A, B, C) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)_mm512_setzero_pd (), (__mmask8)-1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_range_pd(W, U, A, B, C) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)(__m512d)(W), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_range_pd(U, A, B, C) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)_mm512_setzero_pd (), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_range_ps(A, B, C) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)_mm512_setzero_ps (), (__mmask16)-1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_range_ps(W, U, A, B, C) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)(__m512)(W), (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_range_ps(U, A, B, C) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)_mm512_setzero_ps (), (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_range_round_pd(A, B, C, R) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)_mm512_setzero_pd (), (__mmask8)-1, (R))) + +#define _mm512_mask_range_round_pd(W, U, A, B, C, R) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)(__m512d)(W), (__mmask8)(U), (R))) + +#define _mm512_maskz_range_round_pd(U, A, B, C, R) \ + ((__m512d) __builtin_ia32_rangepd512_mask ((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(C), \ + (__v8df)_mm512_setzero_pd (), (__mmask8)(U), (R))) + +#define _mm512_range_round_ps(A, B, C, R) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)_mm512_setzero_ps (), (__mmask16)-1, (R))) + +#define _mm512_mask_range_round_ps(W, U, A, B, C, R) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)(__m512)(W), (__mmask16)(U), (R))) + +#define _mm512_maskz_range_round_ps(U, A, B, C, R) \ + ((__m512) __builtin_ia32_rangeps512_mask ((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(C), \ + (__v16sf)_mm512_setzero_ps (), (__mmask16)(U), (R))) + +#define _mm512_insertf64x2(X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df)(__m512d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), (__v8df)(__m512d) (X), \ + (__mmask8)-1)) + +#define _mm512_mask_insertf64x2(W, U, X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df)(__m512d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), (__v8df)(__m512d) (W), \ + (__mmask8) (U))) + +#define _mm512_maskz_insertf64x2(U, X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x2_512_mask ((__v8df)(__m512d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), \ + (__v8df)(__m512d) _mm512_setzero_pd (), (__mmask8) (U))) + +#define _mm512_inserti64x2(X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di)(__m512i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), (__v8di)(__m512i) (X), (__mmask8)-1)) + +#define _mm512_mask_inserti64x2(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di)(__m512i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), (__v8di)(__m512i) (W), \ + (__mmask8) (U))) + +#define _mm512_maskz_inserti64x2(U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x2_512_mask ((__v8di)(__m512i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), \ + (__v8di)(__m512i) _mm512_setzero_si512 (), (__mmask8) (U))) + +#define _mm512_insertf32x8(X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x8_mask ((__v16sf)(__m512) (X), \ + (__v8sf)(__m256) (Y), (int) (C),\ + (__v16sf)(__m512)_mm512_setzero_ps (),\ + (__mmask16)-1)) + +#define _mm512_mask_insertf32x8(W, U, X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x8_mask ((__v16sf)(__m512) (X), \ + (__v8sf)(__m256) (Y), (int) (C),\ + (__v16sf)(__m512)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_insertf32x8(U, X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x8_mask ((__v16sf)(__m512) (X), \ + (__v8sf)(__m256) (Y), (int) (C),\ + (__v16sf)(__m512)_mm512_setzero_ps (),\ + (__mmask16)(U))) + +#define _mm512_inserti32x8(X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x8_mask ((__v16si)(__m512i) (X), \ + (__v8si)(__m256i) (Y), (int) (C),\ + (__v16si)(__m512i)_mm512_setzero_si512 (),\ + (__mmask16)-1)) + +#define _mm512_mask_inserti32x8(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x8_mask ((__v16si)(__m512i) (X), \ + (__v8si)(__m256i) (Y), (int) (C),\ + (__v16si)(__m512i)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_inserti32x8(U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x8_mask ((__v16si)(__m512i) (X), \ + (__v8si)(__m256i) (Y), (int) (C),\ + (__v16si)(__m512i)_mm512_setzero_si512 (),\ + (__mmask16)(U))) + +#define _mm512_mask_fpclass_pd_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) (__m512d) (X), \ + (int) (C), (__mmask8)(u))) + +#define _mm512_mask_fpclass_ps_mask(u, x, c) \ + ((__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) (__m512) (x),\ + (int) (c),(__mmask16)(u))) + +#define _mm512_fpclass_pd_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) (__m512d) (X), \ + (int) (C), (__mmask8)-1)) + +#define _mm512_fpclass_ps_mask(x, c) \ + ((__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) (__m512) (x),\ + (int) (c),(__mmask16)-1)) + +#endif + +#ifdef __DISABLE_AVX512DQ_512__ +#undef __DISABLE_AVX512DQ_512__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512DQ_512__ */ + +#endif /* _AVX512DQINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512erintrin.h b/template/sysroot/include/avx512erintrin.h new file mode 100644 index 0000000..b3d8a64 --- /dev/null +++ b/template/sysroot/include/avx512erintrin.h @@ -0,0 +1,536 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512ERINTRIN_H_INCLUDED +#define _AVX512ERINTRIN_H_INCLUDED + +#ifndef __AVX512ER__ +#pragma GCC push_options +#pragma GCC target("avx512er,evex512") +#define __DISABLE_AVX512ER__ +#endif /* __AVX512ER__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef double __v8df __attribute__ ((__vector_size__ (64))); +typedef float __v16sf __attribute__ ((__vector_size__ (64))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef float __m512 __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +typedef unsigned char __mmask8; +typedef unsigned short __mmask16; + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_exp2a23_round_pd (__m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A, + (__v8df) _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_exp2a23_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_exp2a23_round_pd (__mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A, + (__v8df) _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_exp2a23_round_ps (__m512 __A, int __R) +{ + return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A, + (__v16sf) _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_exp2a23_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_exp2a23_round_ps (__mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A, + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rcp28_round_pd (__m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A, + (__v8df) _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rcp28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rcp28_round_pd (__mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A, + (__v8df) _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rcp28_round_ps (__m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A, + (__v16sf) _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rcp28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rcp28_round_ps (__mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A, + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp28_round_sd (__m128d __A, __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rcp28sd_round ((__v2df) __B, + (__v2df) __A, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp28_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) __W, + __U, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) + _mm_setzero_pd (), + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp28_round_ss (__m128 __A, __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rcp28ss_round ((__v4sf) __B, + (__v4sf) __A, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp28_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) __W, + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) + _mm_setzero_ps (), + __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rsqrt28_round_pd (__m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A, + (__v8df) _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rsqrt28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rsqrt28_round_pd (__mmask8 __U, __m512d __A, int __R) +{ + return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A, + (__v8df) _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rsqrt28_round_ps (__m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A, + (__v16sf) _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rsqrt28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rsqrt28_round_ps (__mmask16 __U, __m512 __A, int __R) +{ + return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A, + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt28_round_sd (__m128d __A, __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rsqrt28sd_round ((__v2df) __B, + (__v2df) __A, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt28_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) __W, + __U, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R) +{ + return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) + _mm_setzero_pd (), + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt28_round_ss (__m128 __A, __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rsqrt28ss_round ((__v4sf) __B, + (__v4sf) __A, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt28_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) __W, + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R) +{ + return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) + _mm_setzero_ps (), + __U, + __R); +} + +#else +#define _mm512_exp2a23_round_pd(A, C) \ + __builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C) + +#define _mm512_mask_exp2a23_round_pd(W, U, A, C) \ + __builtin_ia32_exp2pd_mask(A, W, U, C) + +#define _mm512_maskz_exp2a23_round_pd(U, A, C) \ + __builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_exp2a23_round_ps(A, C) \ + __builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C) + +#define _mm512_mask_exp2a23_round_ps(W, U, A, C) \ + __builtin_ia32_exp2ps_mask(A, W, U, C) + +#define _mm512_maskz_exp2a23_round_ps(U, A, C) \ + __builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C) + +#define _mm512_rcp28_round_pd(A, C) \ + __builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C) + +#define _mm512_mask_rcp28_round_pd(W, U, A, C) \ + __builtin_ia32_rcp28pd_mask(A, W, U, C) + +#define _mm512_maskz_rcp28_round_pd(U, A, C) \ + __builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_rcp28_round_ps(A, C) \ + __builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C) + +#define _mm512_mask_rcp28_round_ps(W, U, A, C) \ + __builtin_ia32_rcp28ps_mask(A, W, U, C) + +#define _mm512_maskz_rcp28_round_ps(U, A, C) \ + __builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C) + +#define _mm512_rsqrt28_round_pd(A, C) \ + __builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C) + +#define _mm512_mask_rsqrt28_round_pd(W, U, A, C) \ + __builtin_ia32_rsqrt28pd_mask(A, W, U, C) + +#define _mm512_maskz_rsqrt28_round_pd(U, A, C) \ + __builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_rsqrt28_round_ps(A, C) \ + __builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C) + +#define _mm512_mask_rsqrt28_round_ps(W, U, A, C) \ + __builtin_ia32_rsqrt28ps_mask(A, W, U, C) + +#define _mm512_maskz_rsqrt28_round_ps(U, A, C) \ + __builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C) + +#define _mm_rcp28_round_sd(A, B, R) \ + __builtin_ia32_rcp28sd_round(A, B, R) + +#define _mm_mask_rcp28_round_sd(W, U, A, B, R) \ + __builtin_ia32_rcp28sd_mask_round ((A), (B), (W), (U), (R)) + +#define _mm_maskz_rcp28_round_sd(U, A, B, R) \ + __builtin_ia32_rcp28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (), \ + (U), (R)) + +#define _mm_rcp28_round_ss(A, B, R) \ + __builtin_ia32_rcp28ss_round(A, B, R) + +#define _mm_mask_rcp28_round_ss(W, U, A, B, R) \ + __builtin_ia32_rcp28ss_mask_round ((A), (B), (W), (U), (R)) + +#define _mm_maskz_rcp28_round_ss(U, A, B, R) \ + __builtin_ia32_rcp28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (), \ + (U), (R)) + +#define _mm_rsqrt28_round_sd(A, B, R) \ + __builtin_ia32_rsqrt28sd_round(A, B, R) + +#define _mm_mask_rsqrt28_round_sd(W, U, A, B, R) \ + __builtin_ia32_rsqrt28sd_mask_round ((A), (B), (W), (U), (R)) + +#define _mm_maskz_rsqrt28_round_sd(U, A, B, R) \ + __builtin_ia32_rsqrt28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (),\ + (U), (R)) + +#define _mm_rsqrt28_round_ss(A, B, R) \ + __builtin_ia32_rsqrt28ss_round(A, B, R) + +#define _mm_mask_rsqrt28_round_ss(W, U, A, B, R) \ + __builtin_ia32_rsqrt28ss_mask_round ((A), (B), (W), (U), (R)) + +#define _mm_maskz_rsqrt28_round_ss(U, A, B, R) \ + __builtin_ia32_rsqrt28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (),\ + (U), (R)) + +#endif + +#define _mm_mask_rcp28_sd(W, U, A, B)\ + _mm_mask_rcp28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_rcp28_sd(U, A, B)\ + _mm_maskz_rcp28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_rcp28_ss(W, U, A, B)\ + _mm_mask_rcp28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_rcp28_ss(U, A, B)\ + _mm_maskz_rcp28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_rsqrt28_sd(W, U, A, B)\ + _mm_mask_rsqrt28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_rsqrt28_sd(U, A, B)\ + _mm_maskz_rsqrt28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_rsqrt28_ss(W, U, A, B)\ + _mm_mask_rsqrt28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_rsqrt28_ss(U, A, B)\ + _mm_maskz_rsqrt28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm512_exp2a23_pd(A) \ + _mm512_exp2a23_round_pd(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_exp2a23_pd(W, U, A) \ + _mm512_mask_exp2a23_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_exp2a23_pd(U, A) \ + _mm512_maskz_exp2a23_round_pd(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_exp2a23_ps(A) \ + _mm512_exp2a23_round_ps(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_exp2a23_ps(W, U, A) \ + _mm512_mask_exp2a23_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_exp2a23_ps(U, A) \ + _mm512_maskz_exp2a23_round_ps(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_rcp28_pd(A) \ + _mm512_rcp28_round_pd(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_rcp28_pd(W, U, A) \ + _mm512_mask_rcp28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_rcp28_pd(U, A) \ + _mm512_maskz_rcp28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_rcp28_ps(A) \ + _mm512_rcp28_round_ps(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_rcp28_ps(W, U, A) \ + _mm512_mask_rcp28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_rcp28_ps(U, A) \ + _mm512_maskz_rcp28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_rsqrt28_pd(A) \ + _mm512_rsqrt28_round_pd(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_rsqrt28_pd(W, U, A) \ + _mm512_mask_rsqrt28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_rsqrt28_pd(U, A) \ + _mm512_maskz_rsqrt28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_rsqrt28_ps(A) \ + _mm512_rsqrt28_round_ps(A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_mask_rsqrt28_ps(W, U, A) \ + _mm512_mask_rsqrt28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm512_maskz_rsqrt28_ps(U, A) \ + _mm512_maskz_rsqrt28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm_rcp28_sd(A, B) \ + __builtin_ia32_rcp28sd_round(B, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm_rcp28_ss(A, B) \ + __builtin_ia32_rcp28ss_round(B, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm_rsqrt28_sd(A, B) \ + __builtin_ia32_rsqrt28sd_round(B, A, _MM_FROUND_CUR_DIRECTION) + +#define _mm_rsqrt28_ss(A, B) \ + __builtin_ia32_rsqrt28ss_round(B, A, _MM_FROUND_CUR_DIRECTION) + +#ifdef __DISABLE_AVX512ER__ +#undef __DISABLE_AVX512ER__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512ER__ */ + +#endif /* _AVX512ERINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512fintrin.h b/template/sysroot/include/avx512fintrin.h new file mode 100644 index 0000000..3b6749d --- /dev/null +++ b/template/sysroot/include/avx512fintrin.h @@ -0,0 +1,16617 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512FINTRIN_H_INCLUDED +#define _AVX512FINTRIN_H_INCLUDED + +#if !defined (__AVX512F__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512f,no-evex512") +#define __DISABLE_AVX512F__ +#endif /* __AVX512F__ */ + +typedef unsigned char __mmask8; +typedef unsigned short __mmask16; +typedef unsigned int __mmask32; + +/* Constants for mantissa extraction */ +typedef enum +{ + _MM_MANT_NORM_1_2, /* interval [1, 2) */ + _MM_MANT_NORM_p5_2, /* interval [0.5, 2) */ + _MM_MANT_NORM_p5_1, /* interval [0.5, 1) */ + _MM_MANT_NORM_p75_1p5 /* interval [0.75, 1.5) */ +} _MM_MANTISSA_NORM_ENUM; + +typedef enum +{ + _MM_MANT_SIGN_src, /* sign = sign(SRC) */ + _MM_MANT_SIGN_zero, /* sign = 0 */ + _MM_MANT_SIGN_nan /* DEST = NaN if sign(SRC) = 1 */ +} _MM_MANTISSA_SIGN_ENUM; + +/* These _mm{,256}_avx512* intrins are duplicated from their _mm{,256}_* forms + from AVX2 or before. We need to add them to prevent target option mismatch + when calling AVX512 intrins implemented with these intrins under no-evex512 + function attribute. All AVX512 intrins calling those AVX2 intrins or + before will change their calls to these AVX512 version. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_undefined_ps (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128 __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_undefined_pd (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128d __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_setzero_ps (void) +{ + return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f }; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_setzero_pd (void) +{ + return __extension__ (__m128d){ 0.0, 0.0 }; +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_addsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_addsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_addsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_addss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_addss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_addss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_subsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_subsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_subsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_subss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_subss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_subss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +#else +#define _mm_add_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_addsd_round(A, B, C) + +#define _mm_mask_add_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_addsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_add_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_addsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_add_round_ss(A, B, C) \ + (__m128)__builtin_ia32_addss_round(A, B, C) + +#define _mm_mask_add_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_addss_mask_round(A, B, W, U, C) + +#define _mm_maskz_add_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_addss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#define _mm_sub_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_subsd_round(A, B, C) + +#define _mm_mask_sub_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_subsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_sub_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_subsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_sub_round_ss(A, B, C) \ + (__m128)__builtin_ia32_subss_round(A, B, C) + +#define _mm_mask_sub_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_subss_mask_round(A, B, W, U, C) + +#define _mm_maskz_sub_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_subss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#endif + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp14_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rcp14sd ((__v2df) __B, + (__v2df) __A); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __B, + (__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp14_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __B, + (__v2df) __A, + (__v2df) _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp14_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rcp14ss ((__v4sf) __B, + (__v4sf) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp14_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt14_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rsqrt14sd ((__v2df) __B, + (__v2df) __A); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __B, + (__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt14_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __B, + (__v2df) __A, + (__v2df) _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt14_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rsqrt14ss ((__v4sf) __B, + (__v4sf) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt14_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_sqrtsd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_sqrtsd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_round_sd (__mmask8 __U, __m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_sqrtsd_mask_round ((__v2df) __B, + (__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_sqrtss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_sqrtss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_round_ss (__mmask8 __U, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_sqrtss_mask_round ((__v4sf) __B, + (__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_mulsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_mulsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_mulss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_mulss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_mulss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_divsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_divsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_divsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_divss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_divss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_divss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_scalefsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_scalefsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_scalefsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_scalefss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_scalefss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_round_ss (__mmask8 __U, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_scalefss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} +#else +#define _mm_sqrt_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_sqrtsd_mask_round (B, A, \ + (__v2df) _mm_avx512_setzero_pd (), -1, C) + +#define _mm_mask_sqrt_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_sqrtsd_mask_round (B, A, W, U, C) + +#define _mm_maskz_sqrt_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_sqrtsd_mask_round (B, A, \ + (__v2df) _mm_avx512_setzero_pd (), U, C) + +#define _mm_sqrt_round_ss(A, B, C) \ + (__m128)__builtin_ia32_sqrtss_mask_round (B, A, \ + (__v4sf) _mm_avx512_setzero_ps (), -1, C) + +#define _mm_mask_sqrt_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_sqrtss_mask_round (B, A, W, U, C) + +#define _mm_maskz_sqrt_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_sqrtss_mask_round (B, A, \ + (__v4sf) _mm_avx512_setzero_ps (), U, C) + +#define _mm_mul_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_mulsd_round(A, B, C) + +#define _mm_mask_mul_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_mulsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_mul_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_mulsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_mul_round_ss(A, B, C) \ + (__m128)__builtin_ia32_mulss_round(A, B, C) + +#define _mm_mask_mul_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_mulss_mask_round(A, B, W, U, C) + +#define _mm_maskz_mul_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_mulss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#define _mm_div_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_divsd_round(A, B, C) + +#define _mm_mask_div_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_divsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_div_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_divsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_div_round_ss(A, B, C) \ + (__m128)__builtin_ia32_divss_round(A, B, C) + +#define _mm_mask_div_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_divss_mask_round(A, B, W, U, C) + +#define _mm_maskz_div_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_divss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#define _mm_scalef_round_sd(A, B, C) \ + ((__m128d) \ + __builtin_ia32_scalefsd_mask_round ((A), (B), \ + (__v2df) _mm_avx512_undefined_pd (), \ + -1, (C))) + +#define _mm_scalef_round_ss(A, B, C) \ + ((__m128) \ + __builtin_ia32_scalefss_mask_round ((A), (B), \ + (__v4sf) _mm_avx512_undefined_ps (), \ + -1, (C))) + +#define _mm_mask_scalef_round_sd(W, U, A, B, C) \ + ((__m128d) \ + __builtin_ia32_scalefsd_mask_round ((A), (B), (W), (U), (C))) + +#define _mm_mask_scalef_round_ss(W, U, A, B, C) \ + ((__m128) \ + __builtin_ia32_scalefss_mask_round ((A), (B), (W), (U), (C))) + +#define _mm_maskz_scalef_round_sd(U, A, B, C) \ + ((__m128d) \ + __builtin_ia32_scalefsd_mask_round ((A), (B), \ + (__v2df) _mm_avx512_setzero_pd (), \ + (U), (C))) + +#define _mm_maskz_scalef_round_ss(U, A, B, C) \ + ((__m128) \ + __builtin_ia32_scalefss_mask_round ((A), (B), \ + (__v4sf) _mm_avx512_setzero_ps (), \ + (U), (C))) +#endif + +#define _mm_mask_sqrt_sd(W, U, A, B) \ + _mm_mask_sqrt_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_sqrt_sd(U, A, B) \ + _mm_maskz_sqrt_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_sqrt_ss(W, U, A, B) \ + _mm_mask_sqrt_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_sqrt_ss(U, A, B) \ + _mm_maskz_sqrt_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_scalef_sd(W, U, A, B) \ + _mm_mask_scalef_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_scalef_sd(U, A, B) \ + _mm_maskz_scalef_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_scalef_ss(W, U, A, B) \ + _mm_mask_scalef_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_scalef_ss(U, A, B) \ + _mm_maskz_scalef_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu32_sd (__m128d __A, unsigned __B) +{ + return (__m128d) __builtin_ia32_cvtusi2sd32 ((__v2df) __A, __B); +} + +#ifdef __x86_64__ +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundu64_sd (__m128d __A, unsigned long long __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtusi2sd64 ((__v2df) __A, __B, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundi64_sd (__m128d __A, long long __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtsi2sd64 ((__v2df) __A, __B, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsi64_sd (__m128d __A, long long __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtsi2sd64 ((__v2df) __A, __B, __R); +} +#else +#define _mm_cvt_roundu64_sd(A, B, C) \ + (__m128d)__builtin_ia32_cvtusi2sd64(A, B, C) + +#define _mm_cvt_roundi64_sd(A, B, C) \ + (__m128d)__builtin_ia32_cvtsi2sd64(A, B, C) + +#define _mm_cvt_roundsi64_sd(A, B, C) \ + (__m128d)__builtin_ia32_cvtsi2sd64(A, B, C) +#endif + +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundu32_ss (__m128 __A, unsigned __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtusi2ss32 ((__v4sf) __A, __B, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsi32_ss (__m128 __A, int __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsi2ss32 ((__v4sf) __A, __B, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundi32_ss (__m128 __A, int __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsi2ss32 ((__v4sf) __A, __B, __R); +} +#else +#define _mm_cvt_roundu32_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtusi2ss32(A, B, C) + +#define _mm_cvt_roundi32_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtsi2ss32(A, B, C) + +#define _mm_cvt_roundsi32_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtsi2ss32(A, B, C) +#endif + +#ifdef __x86_64__ +#ifdef __OPTIMIZE__ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundu64_ss (__m128 __A, unsigned long long __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtusi2ss64 ((__v4sf) __A, __B, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsi64_ss (__m128 __A, long long __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsi2ss64 ((__v4sf) __A, __B, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundi64_ss (__m128 __A, long long __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsi2ss64 ((__v4sf) __A, __B, __R); +} +#else +#define _mm_cvt_roundu64_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtusi2ss64(A, B, C) + +#define _mm_cvt_roundi64_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtsi2ss64(A, B, C) + +#define _mm_cvt_roundsi64_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtsi2ss64(A, B, C) +#endif + +#endif + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_ss (__m128 __W, __mmask8 __U, const float *__P) +{ + return (__m128) __builtin_ia32_loadss_mask (__P, (__v4sf) __W, __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_ss (__mmask8 __U, const float *__P) +{ + return (__m128) __builtin_ia32_loadss_mask (__P, (__v4sf) _mm_avx512_setzero_ps (), + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_sd (__m128d __W, __mmask8 __U, const double *__P) +{ + return (__m128d) __builtin_ia32_loadsd_mask (__P, (__v2df) __W, __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_sd (__mmask8 __U, const double *__P) +{ + return (__m128d) __builtin_ia32_loadsd_mask (__P, (__v2df) _mm_avx512_setzero_pd (), + __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movess_mask ((__v4sf) __A, (__v4sf) __B, + (__v4sf) __W, __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movess_mask ((__v4sf) __A, (__v4sf) __B, + (__v4sf) _mm_avx512_setzero_ps (), __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movesd_mask ((__v2df) __A, (__v2df) __B, + (__v2df) __W, __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movesd_mask ((__v2df) __A, (__v2df) __B, + (__v2df) _mm_avx512_setzero_pd (), + __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_ss (float *__P, __mmask8 __U, __m128 __A) +{ + __builtin_ia32_storess_mask (__P, (__v4sf) __A, (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_sd (double *__P, __mmask8 __U, __m128d __A) +{ + __builtin_ia32_storesd_mask (__P, (__v2df) __A, (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_round_sd (__m128d __A, __m128d __B, __m128i __C, + const int __imm, const int __R) +{ + return (__m128d) __builtin_ia32_fixupimmsd_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, __imm, + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_round_sd (__m128d __A, __mmask8 __U, __m128d __B, + __m128i __C, const int __imm, const int __R) +{ + return (__m128d) __builtin_ia32_fixupimmsd_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, __imm, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + __m128i __C, const int __imm, const int __R) +{ + return (__m128d) __builtin_ia32_fixupimmsd_maskz ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, + __imm, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_round_ss (__m128 __A, __m128 __B, __m128i __C, + const int __imm, const int __R) +{ + return (__m128) __builtin_ia32_fixupimmss_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_round_ss (__m128 __A, __mmask8 __U, __m128 __B, + __m128i __C, const int __imm, const int __R) +{ + return (__m128) __builtin_ia32_fixupimmss_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + __m128i __C, const int __imm, const int __R) +{ + return (__m128) __builtin_ia32_fixupimmss_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) __U, __R); +} + +#else +#define _mm_fixupimm_round_sd(X, Y, Z, C, R) \ + ((__m128d)__builtin_ia32_fixupimmsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1), (R))) + +#define _mm_mask_fixupimm_round_sd(X, U, Y, Z, C, R) \ + ((__m128d)__builtin_ia32_fixupimmsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#define _mm_maskz_fixupimm_round_sd(U, X, Y, Z, C, R) \ + ((__m128d)__builtin_ia32_fixupimmsd_maskz ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#define _mm_fixupimm_round_ss(X, Y, Z, C, R) \ + ((__m128)__builtin_ia32_fixupimmss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1), (R))) + +#define _mm_mask_fixupimm_round_ss(X, U, Y, Z, C, R) \ + ((__m128)__builtin_ia32_fixupimmss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#define _mm_maskz_fixupimm_round_ss(U, X, Y, Z, C, R) \ + ((__m128)__builtin_ia32_fixupimmss_maskz ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#endif + +#ifdef __x86_64__ +#ifdef __OPTIMIZE__ +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_u64 (__m128 __A, const int __R) +{ + return (unsigned long long) __builtin_ia32_vcvtss2usi64 ((__v4sf) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_si64 (__m128 __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtss2si64 ((__v4sf) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_i64 (__m128 __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtss2si64 ((__v4sf) __A, __R); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_u64 (__m128 __A, const int __R) +{ + return (unsigned long long) __builtin_ia32_vcvttss2usi64 ((__v4sf) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_i64 (__m128 __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_si64 (__m128 __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A, __R); +} +#else +#define _mm_cvt_roundss_u64(A, B) \ + ((unsigned long long)__builtin_ia32_vcvtss2usi64(A, B)) + +#define _mm_cvt_roundss_si64(A, B) \ + ((long long)__builtin_ia32_vcvtss2si64(A, B)) + +#define _mm_cvt_roundss_i64(A, B) \ + ((long long)__builtin_ia32_vcvtss2si64(A, B)) + +#define _mm_cvtt_roundss_u64(A, B) \ + ((unsigned long long)__builtin_ia32_vcvttss2usi64(A, B)) + +#define _mm_cvtt_roundss_i64(A, B) \ + ((long long)__builtin_ia32_vcvttss2si64(A, B)) + +#define _mm_cvtt_roundss_si64(A, B) \ + ((long long)__builtin_ia32_vcvttss2si64(A, B)) +#endif +#endif + +#ifdef __OPTIMIZE__ +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_u32 (__m128 __A, const int __R) +{ + return (unsigned) __builtin_ia32_vcvtss2usi32 ((__v4sf) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_si32 (__m128 __A, const int __R) +{ + return (int) __builtin_ia32_vcvtss2si32 ((__v4sf) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_i32 (__m128 __A, const int __R) +{ + return (int) __builtin_ia32_vcvtss2si32 ((__v4sf) __A, __R); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_u32 (__m128 __A, const int __R) +{ + return (unsigned) __builtin_ia32_vcvttss2usi32 ((__v4sf) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_i32 (__m128 __A, const int __R) +{ + return (int) __builtin_ia32_vcvttss2si32 ((__v4sf) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundss_si32 (__m128 __A, const int __R) +{ + return (int) __builtin_ia32_vcvttss2si32 ((__v4sf) __A, __R); +} +#else +#define _mm_cvt_roundss_u32(A, B) \ + ((unsigned)__builtin_ia32_vcvtss2usi32(A, B)) + +#define _mm_cvt_roundss_si32(A, B) \ + ((int)__builtin_ia32_vcvtss2si32(A, B)) + +#define _mm_cvt_roundss_i32(A, B) \ + ((int)__builtin_ia32_vcvtss2si32(A, B)) + +#define _mm_cvtt_roundss_u32(A, B) \ + ((unsigned)__builtin_ia32_vcvttss2usi32(A, B)) + +#define _mm_cvtt_roundss_si32(A, B) \ + ((int)__builtin_ia32_vcvttss2si32(A, B)) + +#define _mm_cvtt_roundss_i32(A, B) \ + ((int)__builtin_ia32_vcvttss2si32(A, B)) +#endif + +#ifdef __x86_64__ +#ifdef __OPTIMIZE__ +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_u64 (__m128d __A, const int __R) +{ + return (unsigned long long) __builtin_ia32_vcvtsd2usi64 ((__v2df) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_si64 (__m128d __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtsd2si64 ((__v2df) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_i64 (__m128d __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtsd2si64 ((__v2df) __A, __R); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_u64 (__m128d __A, const int __R) +{ + return (unsigned long long) __builtin_ia32_vcvttsd2usi64 ((__v2df) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_si64 (__m128d __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A, __R); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_i64 (__m128d __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A, __R); +} +#else +#define _mm_cvt_roundsd_u64(A, B) \ + ((unsigned long long)__builtin_ia32_vcvtsd2usi64(A, B)) + +#define _mm_cvt_roundsd_si64(A, B) \ + ((long long)__builtin_ia32_vcvtsd2si64(A, B)) + +#define _mm_cvt_roundsd_i64(A, B) \ + ((long long)__builtin_ia32_vcvtsd2si64(A, B)) + +#define _mm_cvtt_roundsd_u64(A, B) \ + ((unsigned long long)__builtin_ia32_vcvttsd2usi64(A, B)) + +#define _mm_cvtt_roundsd_si64(A, B) \ + ((long long)__builtin_ia32_vcvttsd2si64(A, B)) + +#define _mm_cvtt_roundsd_i64(A, B) \ + ((long long)__builtin_ia32_vcvttsd2si64(A, B)) +#endif +#endif + +#ifdef __OPTIMIZE__ +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_u32 (__m128d __A, const int __R) +{ + return (unsigned) __builtin_ia32_vcvtsd2usi32 ((__v2df) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_si32 (__m128d __A, const int __R) +{ + return (int) __builtin_ia32_vcvtsd2si32 ((__v2df) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_i32 (__m128d __A, const int __R) +{ + return (int) __builtin_ia32_vcvtsd2si32 ((__v2df) __A, __R); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_u32 (__m128d __A, const int __R) +{ + return (unsigned) __builtin_ia32_vcvttsd2usi32 ((__v2df) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_i32 (__m128d __A, const int __R) +{ + return (int) __builtin_ia32_vcvttsd2si32 ((__v2df) __A, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsd_si32 (__m128d __A, const int __R) +{ + return (int) __builtin_ia32_vcvttsd2si32 ((__v2df) __A, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_ss (__m128 __A, __m128d __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsd2ss_round ((__v4sf) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundsd_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128d __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsd2ss_mask_round ((__v4sf) __A, + (__v2df) __B, + (__v4sf) __W, + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundsd_ss (__mmask8 __U, __m128 __A, + __m128d __B, const int __R) +{ + return (__m128) __builtin_ia32_cvtsd2ss_mask_round ((__v4sf) __A, + (__v2df) __B, + _mm_avx512_setzero_ps (), + __U, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_sd (__m128d __A, __m128 __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtss2sd_round ((__v2df) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundss_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128 __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtss2sd_mask_round ((__v2df) __A, + (__v4sf) __B, + (__v2df) __W, + __U, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundss_sd (__mmask8 __U, __m128d __A, + __m128 __B, const int __R) +{ + return (__m128d) __builtin_ia32_cvtss2sd_mask_round ((__v2df) __A, + (__v4sf) __B, + _mm_avx512_setzero_pd (), + __U, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_getexpss128_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_getexpsd128_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_round_sd (__m128d __A, __m128d __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128d) __builtin_ia32_getmantsd_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + (__v2df) __W, + __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + (__v2df) + _mm_avx512_setzero_pd(), + __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_round_ss (__m128 __A, __m128 __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128) __builtin_ia32_getmantss_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + (__v4sf) __W, + __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + (__v4sf) + _mm_avx512_setzero_ps(), + __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_round_ss (__m128 __A, __m128 __B, const int __imm, + const int __R) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __A, + (__v4sf) __B, __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_round_ss (__m128 __A, __mmask8 __B, __m128 __C, + __m128 __D, const int __imm, const int __R) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __C, + (__v4sf) __D, __imm, + (__v4sf) __A, + (__mmask8) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_round_ss (__mmask8 __A, __m128 __B, __m128 __C, + const int __imm, const int __R) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __B, + (__v4sf) __C, __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __A, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_round_sd (__m128d __A, __m128d __B, const int __imm, + const int __R) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __A, + (__v2df) __B, __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_round_sd (__m128d __A, __mmask8 __B, __m128d __C, + __m128d __D, const int __imm, const int __R) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __C, + (__v2df) __D, __imm, + (__v2df) __A, + (__mmask8) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_round_sd (__mmask8 __A, __m128d __B, __m128d __C, + const int __imm, const int __R) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __B, + (__v2df) __C, __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __A, + __R); +} + +#else +#define _mm_cvt_roundsd_u32(A, B) \ + ((unsigned)__builtin_ia32_vcvtsd2usi32(A, B)) + +#define _mm_cvt_roundsd_si32(A, B) \ + ((int)__builtin_ia32_vcvtsd2si32(A, B)) + +#define _mm_cvt_roundsd_i32(A, B) \ + ((int)__builtin_ia32_vcvtsd2si32(A, B)) + +#define _mm_cvtt_roundsd_u32(A, B) \ + ((unsigned)__builtin_ia32_vcvttsd2usi32(A, B)) + +#define _mm_cvtt_roundsd_si32(A, B) \ + ((int)__builtin_ia32_vcvttsd2si32(A, B)) + +#define _mm_cvtt_roundsd_i32(A, B) \ + ((int)__builtin_ia32_vcvttsd2si32(A, B)) + +#define _mm_cvt_roundsd_ss(A, B, C) \ + (__m128)__builtin_ia32_cvtsd2ss_round(A, B, C) + +#define _mm_mask_cvt_roundsd_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_cvtsd2ss_mask_round ((A), (B), (W), (U), (C)) + +#define _mm_maskz_cvt_roundsd_ss(U, A, B, C) \ + (__m128)__builtin_ia32_cvtsd2ss_mask_round ((A), (B), _mm_avx512_setzero_ps (), \ + (U), (C)) + +#define _mm_cvt_roundss_sd(A, B, C) \ + (__m128d)__builtin_ia32_cvtss2sd_round(A, B, C) + +#define _mm_mask_cvt_roundss_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_cvtss2sd_mask_round ((A), (B), (W), (U), (C)) + +#define _mm_maskz_cvt_roundss_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_cvtss2sd_mask_round ((A), (B), _mm_avx512_setzero_pd (), \ + (U), (C)) + +#define _mm_getmant_round_sd(X, Y, C, D, R) \ + ((__m128d)__builtin_ia32_getmantsd_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + (R))) + +#define _mm_mask_getmant_round_sd(W, U, X, Y, C, D, R) \ + ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U),\ + (R))) + +#define _mm_maskz_getmant_round_sd(U, X, Y, C, D, R) \ + ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v2df)(__m128d)_mm_avx512_setzero_pd(), \ + (__mmask8)(U),\ + (R))) + +#define _mm_getmant_round_ss(X, Y, C, D, R) \ + ((__m128)__builtin_ia32_getmantss_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + (R))) + +#define _mm_mask_getmant_round_ss(W, U, X, Y, C, D, R) \ + ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U),\ + (R))) + +#define _mm_maskz_getmant_round_ss(U, X, Y, C, D, R) \ + ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps(), \ + (__mmask8)(U),\ + (R))) + +#define _mm_getexp_round_ss(A, B, R) \ + ((__m128)__builtin_ia32_getexpss128_round((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), R)) + +#define _mm_mask_getexp_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_getexpss_mask_round(A, B, W, U, C) + +#define _mm_maskz_getexp_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_getexpss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#define _mm_getexp_round_sd(A, B, R) \ + ((__m128d)__builtin_ia32_getexpsd128_round((__v2df)(__m128d)(A), (__v2df)(__m128d)(B), R)) + +#define _mm_mask_getexp_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_getexp_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_roundscale_round_ss(A, B, I, R) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (A), \ + (__v4sf) (__m128) (B), \ + (int) (I), \ + (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) (-1), \ + (int) (R))) +#define _mm_mask_roundscale_round_ss(A, U, B, C, I, R) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (B), \ + (__v4sf) (__m128) (C), \ + (int) (I), \ + (__v4sf) (__m128) (A), \ + (__mmask8) (U), \ + (int) (R))) +#define _mm_maskz_roundscale_round_ss(U, A, B, I, R) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (A), \ + (__v4sf) (__m128) (B), \ + (int) (I), \ + (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) (U), \ + (int) (R))) +#define _mm_roundscale_round_sd(A, B, I, R) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (A), \ + (__v2df) (__m128d) (B), \ + (int) (I), \ + (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) (-1), \ + (int) (R))) +#define _mm_mask_roundscale_round_sd(A, U, B, C, I, R) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (B), \ + (__v2df) (__m128d) (C), \ + (int) (I), \ + (__v2df) (__m128d) (A), \ + (__mmask8) (U), \ + (int) (R))) +#define _mm_maskz_roundscale_round_sd(U, A, B, I, R) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (A), \ + (__v2df) (__m128d) (B), \ + (int) (I), \ + (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) (U), \ + (int) (R))) + +#endif + +#define _mm_mask_cvtss_sd(W, U, A, B) \ + _mm_mask_cvt_roundss_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_cvtss_sd(U, A, B) \ + _mm_maskz_cvt_roundss_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_mask_cvtsd_ss(W, U, A, B) \ + _mm_mask_cvt_roundsd_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_cvtsd_ss(U, A, B) \ + _mm_maskz_cvt_roundsd_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION) + +#ifdef __OPTIMIZE__ +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftli_mask16 (__mmask16 __A, unsigned int __B) +{ + return (__mmask16) __builtin_ia32_kshiftlihi ((__mmask16) __A, + (__mmask8) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kshiftri_mask16 (__mmask16 __A, unsigned int __B) +{ + return (__mmask16) __builtin_ia32_kshiftrihi ((__mmask16) __A, + (__mmask8) __B); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_round_sd_mask (__m128d __X, __m128d __Y, const int __P, const int __R) +{ + return (__mmask8) __builtin_ia32_cmpsd_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) -1, __R); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_round_sd_mask (__mmask8 __M, __m128d __X, __m128d __Y, + const int __P, const int __R) +{ + return (__mmask8) __builtin_ia32_cmpsd_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) __M, __R); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_round_ss_mask (__m128 __X, __m128 __Y, const int __P, const int __R) +{ + return (__mmask8) __builtin_ia32_cmpss_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) -1, __R); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_round_ss_mask (__mmask8 __M, __m128 __X, __m128 __Y, + const int __P, const int __R) +{ + return (__mmask8) __builtin_ia32_cmpss_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) __M, __R); +} + +#else +#define _kshiftli_mask16(X, Y) \ + ((__mmask16) __builtin_ia32_kshiftlihi ((__mmask16)(X), (__mmask8)(Y))) + +#define _kshiftri_mask16(X, Y) \ + ((__mmask16) __builtin_ia32_kshiftrihi ((__mmask16)(X), (__mmask8)(Y))) + +#define _mm_cmp_round_sd_mask(X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmpsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + (__mmask8)-1, R)) + +#define _mm_mask_cmp_round_sd_mask(M, X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmpsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + (M), R)) + +#define _mm_cmp_round_ss_mask(X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmpss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P), \ + (__mmask8)-1, R)) + +#define _mm_mask_cmp_round_ss_mask(M, X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmpss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P), \ + (M), R)) + +#endif + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortest_mask16_u8 (__mmask16 __A, __mmask16 __B, unsigned char *__CF) +{ + *__CF = (unsigned char) __builtin_ia32_kortestchi (__A, __B); + return (unsigned char) __builtin_ia32_kortestzhi (__A, __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestz_mask16_u8 (__mmask16 __A, __mmask16 __B) +{ + return (unsigned char) __builtin_ia32_kortestzhi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kortestc_mask16_u8 (__mmask16 __A, __mmask16 __B) +{ + return (unsigned char) __builtin_ia32_kortestchi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtmask16_u32 (__mmask16 __A) +{ + return (unsigned int) __builtin_ia32_kmovw ((__mmask16 ) __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cvtu32_mask16 (unsigned int __A) +{ + return (__mmask16) __builtin_ia32_kmovw ((__mmask16 ) __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_load_mask16 (__mmask16 *__A) +{ + return (__mmask16) __builtin_ia32_kmovw (*(__mmask16 *) __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_store_mask16 (__mmask16 *__A, __mmask16 __B) +{ + *(__mmask16 *) __A = __builtin_ia32_kmovw (__B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kand_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kandhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kandn_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kandnhi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kor_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxnor_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kxnorhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kxor_mask16 (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kxorhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_knot_mask16 (__mmask16 __A) +{ + return (__mmask16) __builtin_ia32_knothi ((__mmask16) __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_kunpackb_mask16 (__mmask8 __A, __mmask8 __B) +{ + return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_maxsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_maxsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_maxss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_maxss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_maxss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_round_sd (__m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_minsd_round ((__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_round_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_minsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_round_sd (__mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_minsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_round_ss (__m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_minss_round ((__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_round_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_minss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_round_ss (__mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_minss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, __R); +} + +#else +#define _mm_max_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_maxsd_round(A, B, C) + +#define _mm_mask_max_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_maxsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_max_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_maxsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_max_round_ss(A, B, C) \ + (__m128)__builtin_ia32_maxss_round(A, B, C) + +#define _mm_mask_max_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_maxss_mask_round(A, B, W, U, C) + +#define _mm_maskz_max_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_maxss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#define _mm_min_round_sd(A, B, C) \ + (__m128d)__builtin_ia32_minsd_round(A, B, C) + +#define _mm_mask_min_round_sd(W, U, A, B, C) \ + (__m128d)__builtin_ia32_minsd_mask_round(A, B, W, U, C) + +#define _mm_maskz_min_round_sd(U, A, B, C) \ + (__m128d)__builtin_ia32_minsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U, C) + +#define _mm_min_round_ss(A, B, C) \ + (__m128)__builtin_ia32_minss_round(A, B, C) + +#define _mm_mask_min_round_ss(W, U, A, B, C) \ + (__m128)__builtin_ia32_minss_mask_round(A, B, W, U, C) + +#define _mm_maskz_min_round_ss(U, A, B, C) \ + (__m128)__builtin_ia32_minss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U, C) + +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_round_sd (__m128d __W, __m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_round ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_round_ss (__m128 __W, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_round ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_round_sd (__m128d __W, __m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_round ((__v2df) __W, + (__v2df) __A, + -(__v2df) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_round_ss (__m128 __W, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_round ((__v4sf) __W, + (__v4sf) __A, + -(__v4sf) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_round_sd (__m128d __W, __m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_round ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_round_ss (__m128 __W, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_round ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_round_sd (__m128d __W, __m128d __A, __m128d __B, const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_round ((__v2df) __W, + -(__v2df) __A, + -(__v2df) __B, + __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_round_ss (__m128 __W, __m128 __A, __m128 __B, const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_round ((__v4sf) __W, + -(__v4sf) __A, + -(__v4sf) __B, + __R); +} +#else +#define _mm_fmadd_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_round(A, B, C, R) + +#define _mm_fmadd_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_round(A, B, C, R) + +#define _mm_fmsub_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_round(A, B, -(C), R) + +#define _mm_fmsub_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_round(A, B, -(C), R) + +#define _mm_fnmadd_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_round(A, -(B), C, R) + +#define _mm_fnmadd_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_round(A, -(B), C, R) + +#define _mm_fnmsub_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_round(A, -(B), -(C), R) + +#define _mm_fnmsub_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_round(A, -(B), -(C), R) +#endif + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + (__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + (__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + (__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + (__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + -(__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + -(__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + -(__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + -(__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_round_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_round_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_round_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_round_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + (__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + (__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_round_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W, + (__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_round_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U, + const int __R) +{ + return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W, + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_round_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + (__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_round_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + (__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_round_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_round_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_round_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_round_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_round_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_mask ((__v2df) __W, + -(__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_round_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W, + -(__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_round_sd (__m128d __W, __m128d __A, __m128d __B, __mmask8 __U, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W, + -(__v2df) __A, + (__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_round_ss (__m128 __W, __m128 __A, __m128 __B, __mmask8 __U, + const int __R) +{ + return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W, + -(__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_round_sd (__mmask8 __U, __m128d __W, __m128d __A, __m128d __B, + const int __R) +{ + return (__m128d) __builtin_ia32_vfmaddsd3_maskz ((__v2df) __W, + -(__v2df) __A, + -(__v2df) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_round_ss (__mmask8 __U, __m128 __W, __m128 __A, __m128 __B, + const int __R) +{ + return (__m128) __builtin_ia32_vfmaddss3_maskz ((__v4sf) __W, + -(__v4sf) __A, + -(__v4sf) __B, + (__mmask8) __U, __R); +} +#else +#define _mm_mask_fmadd_round_sd(A, U, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask (A, B, C, U, R) + +#define _mm_mask_fmadd_round_ss(A, U, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask (A, B, C, U, R) + +#define _mm_mask3_fmadd_round_sd(A, B, C, U, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask3 (A, B, C, U, R) + +#define _mm_mask3_fmadd_round_ss(A, B, C, U, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask3 (A, B, C, U, R) + +#define _mm_maskz_fmadd_round_sd(U, A, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_maskz (A, B, C, U, R) + +#define _mm_maskz_fmadd_round_ss(U, A, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_maskz (A, B, C, U, R) + +#define _mm_mask_fmsub_round_sd(A, U, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask (A, B, -(C), U, R) + +#define _mm_mask_fmsub_round_ss(A, U, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask (A, B, -(C), U, R) + +#define _mm_mask3_fmsub_round_sd(A, B, C, U, R) \ + (__m128d) __builtin_ia32_vfmsubsd3_mask3 (A, B, C, U, R) + +#define _mm_mask3_fmsub_round_ss(A, B, C, U, R) \ + (__m128) __builtin_ia32_vfmsubss3_mask3 (A, B, C, U, R) + +#define _mm_maskz_fmsub_round_sd(U, A, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_maskz (A, B, -(C), U, R) + +#define _mm_maskz_fmsub_round_ss(U, A, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_maskz (A, B, -(C), U, R) + +#define _mm_mask_fnmadd_round_sd(A, U, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask (A, -(B), C, U, R) + +#define _mm_mask_fnmadd_round_ss(A, U, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask (A, -(B), C, U, R) + +#define _mm_mask3_fnmadd_round_sd(A, B, C, U, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask3 (A, -(B), C, U, R) + +#define _mm_mask3_fnmadd_round_ss(A, B, C, U, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask3 (A, -(B), C, U, R) + +#define _mm_maskz_fnmadd_round_sd(U, A, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_maskz (A, -(B), C, U, R) + +#define _mm_maskz_fnmadd_round_ss(U, A, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_maskz (A, -(B), C, U, R) + +#define _mm_mask_fnmsub_round_sd(A, U, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_mask (A, -(B), -(C), U, R) + +#define _mm_mask_fnmsub_round_ss(A, U, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_mask (A, -(B), -(C), U, R) + +#define _mm_mask3_fnmsub_round_sd(A, B, C, U, R) \ + (__m128d) __builtin_ia32_vfmsubsd3_mask3 (A, -(B), C, U, R) + +#define _mm_mask3_fnmsub_round_ss(A, B, C, U, R) \ + (__m128) __builtin_ia32_vfmsubss3_mask3 (A, -(B), C, U, R) + +#define _mm_maskz_fnmsub_round_sd(U, A, B, C, R) \ + (__m128d) __builtin_ia32_vfmaddsd3_maskz (A, -(B), -(C), U, R) + +#define _mm_maskz_fnmsub_round_ss(U, A, B, C, R) \ + (__m128) __builtin_ia32_vfmaddss3_maskz (A, -(B), -(C), U, R) +#endif + +#ifdef __OPTIMIZE__ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comi_round_ss (__m128 __A, __m128 __B, const int __P, const int __R) +{ + return __builtin_ia32_vcomiss ((__v4sf) __A, (__v4sf) __B, __P, __R); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comi_round_sd (__m128d __A, __m128d __B, const int __P, const int __R) +{ + return __builtin_ia32_vcomisd ((__v2df) __A, (__v2df) __B, __P, __R); +} +#else +#define _mm_comi_round_ss(A, B, C, D)\ +__builtin_ia32_vcomiss(A, B, C, D) +#define _mm_comi_round_sd(A, B, C, D)\ +__builtin_ia32_vcomisd(A, B, C, D) +#endif + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_addsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_addsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_addss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_addss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_subsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_subsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_subss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_subss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_mulsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_mulsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B) +{ + return (__m128) __builtin_ia32_mulss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_mulss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_sd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_divsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_divsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_ss (__m128 __W, __mmask8 __U, __m128 __A, + __m128 __B) +{ + return (__m128) __builtin_ia32_divss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_divss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_maxsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_maxsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_minsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_minsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_scalefsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_scalefss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __x86_64__ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu64_ss (__m128 __A, unsigned long long __B) +{ + return (__m128) __builtin_ia32_cvtusi2ss64 ((__v4sf) __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu64_sd (__m128d __A, unsigned long long __B) +{ + return (__m128d) __builtin_ia32_cvtusi2sd64 ((__v2df) __A, __B, + _MM_FROUND_CUR_DIRECTION); +} +#endif + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu32_ss (__m128 __A, unsigned __B) +{ + return (__m128) __builtin_ia32_cvtusi2ss32 ((__v4sf) __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_sd (__m128d __A, __m128d __B, __m128i __C, const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmsd_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, __imm, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_sd (__m128d __A, __mmask8 __U, __m128d __B, + __m128i __C, const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmsd_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_sd (__mmask8 __U, __m128d __A, __m128d __B, + __m128i __C, const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmsd_maskz ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, + __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_ss (__m128 __A, __m128 __B, __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmss_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_ss (__m128 __A, __mmask8 __U, __m128 __B, + __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmss_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_ss (__mmask8 __U, __m128 __A, __m128 __B, + __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmss_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm_fixupimm_sd(X, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_fixupimm_sd(X, U, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_fixupimm_sd(U, X, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmsd_maskz ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_fixupimm_ss(X, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_fixupimm_ss(X, U, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_fixupimm_ss(U, X, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmss_maskz ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#endif + +#ifdef __x86_64__ +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_u64 (__m128 __A) +{ + return (unsigned long long) __builtin_ia32_vcvtss2usi64 ((__v4sf) + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_u64 (__m128 __A) +{ + return (unsigned long long) __builtin_ia32_vcvttss2usi64 ((__v4sf) + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_i64 (__m128 __A) +{ + return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A, + _MM_FROUND_CUR_DIRECTION); +} +#endif /* __x86_64__ */ + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_u32 (__m128 __A) +{ + return (unsigned) __builtin_ia32_vcvtss2usi32 ((__v4sf) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_u32 (__m128 __A) +{ + return (unsigned) __builtin_ia32_vcvttss2usi32 ((__v4sf) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_i32 (__m128 __A) +{ + return (int) __builtin_ia32_vcvttss2si32 ((__v4sf) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_i32 (__m128d __A) +{ + return (int) __builtin_ia32_cvtsd2si ((__v2df) __A); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_i32 (__m128 __A) +{ + return (int) __builtin_ia32_cvtss2si ((__v4sf) __A); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti32_sd (__m128d __A, int __B) +{ + return (__m128d) __builtin_ia32_cvtsi2sd ((__v2df) __A, __B); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti32_ss (__m128 __A, int __B) +{ + return (__m128) __builtin_ia32_cvtsi2ss ((__v4sf) __A, __B); +} + +#ifdef __x86_64__ +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_u64 (__m128d __A) +{ + return (unsigned long long) __builtin_ia32_vcvtsd2usi64 ((__v2df) + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_u64 (__m128d __A) +{ + return (unsigned long long) __builtin_ia32_vcvttsd2usi64 ((__v2df) + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_i64 (__m128d __A) +{ + return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_i64 (__m128d __A) +{ + return (long long) __builtin_ia32_cvtsd2si64 ((__v2df) __A); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_i64 (__m128 __A) +{ + return (long long) __builtin_ia32_cvtss2si64 ((__v4sf) __A); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti64_sd (__m128d __A, long long __B) +{ + return (__m128d) __builtin_ia32_cvtsi642sd ((__v2df) __A, __B); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti64_ss (__m128 __A, long long __B) +{ + return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B); +} +#endif /* __x86_64__ */ + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_u32 (__m128d __A) +{ + return (unsigned) __builtin_ia32_vcvtsd2usi32 ((__v2df) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_u32 (__m128d __A) +{ + return (unsigned) __builtin_ia32_vcvttsd2usi32 ((__v2df) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_i32 (__m128d __A) +{ + return (int) __builtin_ia32_vcvttsd2si32 ((__v2df) __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_getexpss128_round ((__v4sf) __A, + (__v4sf) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_getexpsd128_round ((__v2df) __A, + (__v2df) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_sd (__m128d __A, __m128d __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128d) __builtin_ia32_getmantsd_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B, + _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + (__v2df) __W, + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_sd (__mmask8 __U, __m128d __A, __m128d __B, + _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A, + (__v2df) __B, + (__D << 2) | __C, + (__v2df) + _mm_avx512_setzero_pd(), + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_ss (__m128 __A, __m128 __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128) __builtin_ia32_getmantss_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + (__v4sf) __W, + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_ss (__mmask8 __U, __m128 __A, __m128 __B, + _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A, + (__v4sf) __B, + (__D << 2) | __C, + (__v4sf) + _mm_avx512_setzero_ps(), + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_ss (__m128 __A, __m128 __B, const int __imm) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __A, + (__v4sf) __B, __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_ss (__m128 __A, __mmask8 __B, __m128 __C, __m128 __D, + const int __imm) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __C, + (__v4sf) __D, __imm, + (__v4sf) __A, + (__mmask8) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_ss (__mmask8 __A, __m128 __B, __m128 __C, + const int __imm) +{ + return (__m128) + __builtin_ia32_rndscaless_mask_round ((__v4sf) __B, + (__v4sf) __C, __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_sd (__m128d __A, __m128d __B, const int __imm) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __A, + (__v2df) __B, __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_sd (__m128d __A, __mmask8 __B, __m128d __C, __m128d __D, + const int __imm) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __C, + (__v2df) __D, __imm, + (__v2df) __A, + (__mmask8) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_sd (__mmask8 __A, __m128d __B, __m128d __C, + const int __imm) +{ + return (__m128d) + __builtin_ia32_rndscalesd_mask_round ((__v2df) __B, + (__v2df) __C, __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_sd_mask (__m128d __X, __m128d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpsd_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_sd_mask (__mmask8 __M, __m128d __X, __m128d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpsd_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) __M, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ss_mask (__m128 __X, __m128 __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpss_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_ss_mask (__mmask8 __M, __m128 __X, __m128 __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpss_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) __M, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm_getmant_sd(X, Y, C, D) \ + ((__m128d)__builtin_ia32_getmantsd_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_getmant_sd(W, U, X, Y, C, D) \ + ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_getmant_sd(U, X, Y, C, D) \ + ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v2df)_mm_avx512_setzero_pd(), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_getmant_ss(X, Y, C, D) \ + ((__m128)__builtin_ia32_getmantss_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_getmant_ss(W, U, X, Y, C, D) \ + ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_getmant_ss(U, X, Y, C, D) \ + ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v4sf)_mm_avx512_setzero_ps(), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_getexp_ss(A, B) \ + ((__m128)__builtin_ia32_getexpss128_round((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_getexp_ss(W, U, A, B) \ + (__m128)__builtin_ia32_getexpss_mask_round(A, B, W, U,\ + _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_getexp_ss(U, A, B) \ + (__m128)__builtin_ia32_getexpss_mask_round(A, B, (__v4sf)_mm_avx512_setzero_ps(), U,\ + _MM_FROUND_CUR_DIRECTION) + +#define _mm_getexp_sd(A, B) \ + ((__m128d)__builtin_ia32_getexpsd128_round((__v2df)(__m128d)(A), (__v2df)(__m128d)(B),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_getexp_sd(W, U, A, B) \ + (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, W, U,\ + _MM_FROUND_CUR_DIRECTION) + +#define _mm_maskz_getexp_sd(U, A, B) \ + (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, (__v2df)_mm_avx512_setzero_pd(), U,\ + _MM_FROUND_CUR_DIRECTION) + +#define _mm_roundscale_ss(A, B, I) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (A), \ + (__v4sf) (__m128) (B), \ + (int) (I), \ + (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) (-1), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm_mask_roundscale_ss(A, U, B, C, I) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (B), \ + (__v4sf) (__m128) (C), \ + (int) (I), \ + (__v4sf) (__m128) (A), \ + (__mmask8) (U), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm_maskz_roundscale_ss(U, A, B, I) \ + ((__m128) \ + __builtin_ia32_rndscaless_mask_round ((__v4sf) (__m128) (A), \ + (__v4sf) (__m128) (B), \ + (int) (I), \ + (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8) (U), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm_roundscale_sd(A, B, I) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (A), \ + (__v2df) (__m128d) (B), \ + (int) (I), \ + (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) (-1), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm_mask_roundscale_sd(A, U, B, C, I) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (B), \ + (__v2df) (__m128d) (C), \ + (int) (I), \ + (__v2df) (__m128d) (A), \ + (__mmask8) (U), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm_maskz_roundscale_sd(U, A, B, I) \ + ((__m128d) \ + __builtin_ia32_rndscalesd_mask_round ((__v2df) (__m128d) (A), \ + (__v2df) (__m128d) (B), \ + (int) (I), \ + (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8) (U), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_cmp_sd_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + (__mmask8)-1,_MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_cmp_sd_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpsd_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + M,_MM_FROUND_CUR_DIRECTION)) + +#define _mm_cmp_ss_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P), \ + (__mmask8)-1,_MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_cmp_ss_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpss_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P), \ + M,_MM_FROUND_CUR_DIRECTION)) + +#endif + +#ifdef __DISABLE_AVX512F__ +#undef __DISABLE_AVX512F__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512F__ */ + +#if !defined (__AVX512F__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512f,evex512") +#define __DISABLE_AVX512F_512__ +#endif /* __AVX512F_512__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef double __v8df __attribute__ ((__vector_size__ (64))); +typedef float __v16sf __attribute__ ((__vector_size__ (64))); +typedef long long __v8di __attribute__ ((__vector_size__ (64))); +typedef unsigned long long __v8du __attribute__ ((__vector_size__ (64))); +typedef int __v16si __attribute__ ((__vector_size__ (64))); +typedef unsigned int __v16su __attribute__ ((__vector_size__ (64))); +typedef short __v32hi __attribute__ ((__vector_size__ (64))); +typedef unsigned short __v32hu __attribute__ ((__vector_size__ (64))); +typedef char __v64qi __attribute__ ((__vector_size__ (64))); +typedef unsigned char __v64qu __attribute__ ((__vector_size__ (64))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef float __m512 __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +/* Unaligned version of the same type. */ +typedef float __m512_u __attribute__ ((__vector_size__ (64), __may_alias__, __aligned__ (1))); +typedef long long __m512i_u __attribute__ ((__vector_size__ (64), __may_alias__, __aligned__ (1))); +typedef double __m512d_u __attribute__ ((__vector_size__ (64), __may_alias__, __aligned__ (1))); + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_int2mask (int __M) +{ + return (__mmask16) __M; +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2int (__mmask16 __M) +{ + return (int) __M; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_epi64 (long long __A, long long __B, long long __C, + long long __D, long long __E, long long __F, + long long __G, long long __H) +{ + return __extension__ (__m512i) (__v8di) + { __H, __G, __F, __E, __D, __C, __B, __A }; +} + +/* Create the vector [A B C D E F G H I J K L M N O P]. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_epi32 (int __A, int __B, int __C, int __D, + int __E, int __F, int __G, int __H, + int __I, int __J, int __K, int __L, + int __M, int __N, int __O, int __P) +{ + return __extension__ (__m512i)(__v16si) + { __P, __O, __N, __M, __L, __K, __J, __I, + __H, __G, __F, __E, __D, __C, __B, __A }; +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_epi16 (short __q31, short __q30, short __q29, short __q28, + short __q27, short __q26, short __q25, short __q24, + short __q23, short __q22, short __q21, short __q20, + short __q19, short __q18, short __q17, short __q16, + short __q15, short __q14, short __q13, short __q12, + short __q11, short __q10, short __q09, short __q08, + short __q07, short __q06, short __q05, short __q04, + short __q03, short __q02, short __q01, short __q00) +{ + return __extension__ (__m512i)(__v32hi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15, + __q16, __q17, __q18, __q19, __q20, __q21, __q22, __q23, + __q24, __q25, __q26, __q27, __q28, __q29, __q30, __q31 + }; +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_epi8 (char __q63, char __q62, char __q61, char __q60, + char __q59, char __q58, char __q57, char __q56, + char __q55, char __q54, char __q53, char __q52, + char __q51, char __q50, char __q49, char __q48, + char __q47, char __q46, char __q45, char __q44, + char __q43, char __q42, char __q41, char __q40, + char __q39, char __q38, char __q37, char __q36, + char __q35, char __q34, char __q33, char __q32, + char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return __extension__ (__m512i)(__v64qi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15, + __q16, __q17, __q18, __q19, __q20, __q21, __q22, __q23, + __q24, __q25, __q26, __q27, __q28, __q29, __q30, __q31, + __q32, __q33, __q34, __q35, __q36, __q37, __q38, __q39, + __q40, __q41, __q42, __q43, __q44, __q45, __q46, __q47, + __q48, __q49, __q50, __q51, __q52, __q53, __q54, __q55, + __q56, __q57, __q58, __q59, __q60, __q61, __q62, __q63 + }; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_pd (double __A, double __B, double __C, double __D, + double __E, double __F, double __G, double __H) +{ + return __extension__ (__m512d) + { __H, __G, __F, __E, __D, __C, __B, __A }; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_ps (float __A, float __B, float __C, float __D, + float __E, float __F, float __G, float __H, + float __I, float __J, float __K, float __L, + float __M, float __N, float __O, float __P) +{ + return __extension__ (__m512) + { __P, __O, __N, __M, __L, __K, __J, __I, + __H, __G, __F, __E, __D, __C, __B, __A }; +} + +#define _mm512_setr_epi64(e0,e1,e2,e3,e4,e5,e6,e7) \ + _mm512_set_epi64(e7,e6,e5,e4,e3,e2,e1,e0) + +#define _mm512_setr_epi32(e0,e1,e2,e3,e4,e5,e6,e7, \ + e8,e9,e10,e11,e12,e13,e14,e15) \ + _mm512_set_epi32(e15,e14,e13,e12,e11,e10,e9,e8,e7,e6,e5,e4,e3,e2,e1,e0) + +#define _mm512_setr_pd(e0,e1,e2,e3,e4,e5,e6,e7) \ + _mm512_set_pd(e7,e6,e5,e4,e3,e2,e1,e0) + +#define _mm512_setr_ps(e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15) \ + _mm512_set_ps(e15,e14,e13,e12,e11,e10,e9,e8,e7,e6,e5,e4,e3,e2,e1,e0) + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_undefined_ps (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m512 __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +#define _mm512_undefined _mm512_undefined_ps + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_undefined_pd (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m512d __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_undefined_epi32 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m512i __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +#define _mm512_undefined_si512 _mm512_undefined_epi32 + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_epi8 (char __A) +{ + return __extension__ (__m512i)(__v64qi) + { __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_epi16 (short __A) +{ + return __extension__ (__m512i)(__v32hi) + { __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A }; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_pd (double __A) +{ + return __extension__ (__m512d)(__v8df) + { __A, __A, __A, __A, __A, __A, __A, __A }; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_ps (float __A) +{ + return __extension__ (__m512)(__v16sf) + { __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A }; +} + +/* Create the vector [A B C D A B C D A B C D A B C D]. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set4_epi32 (int __A, int __B, int __C, int __D) +{ + return __extension__ (__m512i)(__v16si) + { __D, __C, __B, __A, __D, __C, __B, __A, + __D, __C, __B, __A, __D, __C, __B, __A }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set4_epi64 (long long __A, long long __B, long long __C, + long long __D) +{ + return __extension__ (__m512i) (__v8di) + { __D, __C, __B, __A, __D, __C, __B, __A }; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set4_pd (double __A, double __B, double __C, double __D) +{ + return __extension__ (__m512d) + { __D, __C, __B, __A, __D, __C, __B, __A }; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set4_ps (float __A, float __B, float __C, float __D) +{ + return __extension__ (__m512) + { __D, __C, __B, __A, __D, __C, __B, __A, + __D, __C, __B, __A, __D, __C, __B, __A }; +} + +#define _mm512_setr4_epi64(e0,e1,e2,e3) \ + _mm512_set4_epi64(e3,e2,e1,e0) + +#define _mm512_setr4_epi32(e0,e1,e2,e3) \ + _mm512_set4_epi32(e3,e2,e1,e0) + +#define _mm512_setr4_pd(e0,e1,e2,e3) \ + _mm512_set4_pd(e3,e2,e1,e0) + +#define _mm512_setr4_ps(e0,e1,e2,e3) \ + _mm512_set4_ps(e3,e2,e1,e0) + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero_ps (void) +{ + return __extension__ (__m512){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero (void) +{ + return _mm512_setzero_ps (); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero_pd (void) +{ + return __extension__ (__m512d) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero_epi32 (void) +{ + return __extension__ (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero_si512 (void) +{ + return __extension__ (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 }; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_movapd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_movapd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movaps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movaps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_pd (void const *__P) +{ + return *(__m512d *) __P; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_load_pd (__m512d __W, __mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *) __P, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_load_pd (__mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *) __P, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_pd (void *__P, __m512d __A) +{ + *(__m512d *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_store_pd (void *__P, __mmask8 __U, __m512d __A) +{ + __builtin_ia32_storeapd512_mask ((__v8df *) __P, (__v8df) __A, + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_ps (void const *__P) +{ + return *(__m512 *) __P; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_load_ps (__m512 __W, __mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *) __P, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_load_ps (__mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *) __P, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_ps (void *__P, __m512 __A) +{ + *(__m512 *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_store_ps (void *__P, __mmask16 __U, __m512 __A) +{ + __builtin_ia32_storeaps512_mask ((__v16sf *) __P, (__v16sf) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdqa64_512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdqa64_512_mask ((__v8di) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_epi64 (void const *__P) +{ + return *(__m512i *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_load_epi64 (__m512i __W, __mmask8 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_load_epi64 (__mmask8 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_epi64 (void *__P, __m512i __A) +{ + *(__m512i *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_store_epi64 (void *__P, __mmask8 __U, __m512i __A) +{ + __builtin_ia32_movdqa64store512_mask ((__v8di *) __P, (__v8di) __A, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mov_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdqa32_512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mov_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_movdqa32_512_mask ((__v16si) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_si512 (void const *__P) +{ + return *(__m512i *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_epi32 (void const *__P) +{ + return *(__m512i *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_load_epi32 (__mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_si512 (void *__P, __m512i __A) +{ + *(__m512i *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_epi32 (void *__P, __m512i __A) +{ + *(__m512i *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_store_epi32 (void *__P, __mmask16 __U, __m512i __A) +{ + __builtin_ia32_movdqa32store512_mask ((__v16si *) __P, (__v16si) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mullo_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A * (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mullo_epi32 (__mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mullo_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mullox_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A * (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mullox_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) +{ + return _mm512_mask_mov_epi64 (__W, __M, _mm512_mullox_epi64 (__A, __B)); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sllv_epi32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sllv_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sllv_epi32 (__mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srav_epi32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srav_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srav_epi32 (__mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srlv_epi32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srlv_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srlv_epi32 (__mmask16 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X, + (__v16si) __Y, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A + (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A - (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sllv_epi64 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sllv_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sllv_epi64 (__mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srav_epi64 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srav_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srav_epi64 (__mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srlv_epi64 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srlv_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srlv_epi64 (__mmask8 __U, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A + (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_epi32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_epi32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_epi32 (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A - (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_epu32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_epu32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_epu32 (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X, + (__v16si) __Y, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_slli_epi64 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_slli_epi64 (__m512i __W, __mmask8 __U, __m512i __A, + unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllqi512_mask ((__v8di) __A, __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_slli_epi64 (__mmask8 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psllqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} +#else +#define _mm512_slli_epi64(X, C) \ + ((__m512i) __builtin_ia32_psllqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_undefined_epi32 (), \ + (__mmask8)-1)) + +#define _mm512_mask_slli_epi64(W, U, X, C) \ + ((__m512i) __builtin_ia32_psllqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(U))) + +#define _mm512_maskz_slli_epi64(U, X, C) \ + ((__m512i) __builtin_ia32_psllqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sll_epi64 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sll_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sll_epi64 (__mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srli_epi64 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrlqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srli_epi64 (__m512i __W, __mmask8 __U, + __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrlqi512_mask ((__v8di) __A, __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srli_epi64 (__mmask8 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrlqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} +#else +#define _mm512_srli_epi64(X, C) \ + ((__m512i) __builtin_ia32_psrlqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_undefined_epi32 (), \ + (__mmask8)-1)) + +#define _mm512_mask_srli_epi64(W, U, X, C) \ + ((__m512i) __builtin_ia32_psrlqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(U))) + +#define _mm512_maskz_srli_epi64(U, X, C) \ + ((__m512i) __builtin_ia32_psrlqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srl_epi64 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srl_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srl_epi64 (__mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srai_epi64 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psraqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srai_epi64 (__m512i __W, __mmask8 __U, __m512i __A, + unsigned int __B) +{ + return (__m512i) __builtin_ia32_psraqi512_mask ((__v8di) __A, __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srai_epi64 (__mmask8 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psraqi512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} +#else +#define _mm512_srai_epi64(X, C) \ + ((__m512i) __builtin_ia32_psraqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_undefined_epi32 (), \ + (__mmask8)-1)) + +#define _mm512_mask_srai_epi64(W, U, X, C) \ + ((__m512i) __builtin_ia32_psraqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(U))) + +#define _mm512_maskz_srai_epi64(U, X, C) \ + ((__m512i) __builtin_ia32_psraqi512_mask ((__v8di)(__m512i)(X), \ + (unsigned int)(C), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sra_epi64 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sra_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sra_epi64 (__mmask8 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A, + (__v2di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_slli_epi32 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_pslldi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_slli_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + unsigned int __B) +{ + return (__m512i) __builtin_ia32_pslldi512_mask ((__v16si) __A, __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_slli_epi32 (__mmask16 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_pslldi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} +#else +#define _mm512_slli_epi32(X, C) \ + ((__m512i) __builtin_ia32_pslldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_undefined_epi32 (), \ + (__mmask16)-1)) + +#define _mm512_mask_slli_epi32(W, U, X, C) \ + ((__m512i) __builtin_ia32_pslldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)(W), \ + (__mmask16)(U))) + +#define _mm512_maskz_slli_epi32(U, X, C) \ + ((__m512i) __builtin_ia32_pslldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_setzero_si512 (), \ + (__mmask16)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sll_epi32 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sll_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sll_epi32 (__mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srli_epi32 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrldi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srli_epi32 (__m512i __W, __mmask16 __U, + __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrldi512_mask ((__v16si) __A, __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srli_epi32 (__mmask16 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psrldi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} +#else +#define _mm512_srli_epi32(X, C) \ + ((__m512i) __builtin_ia32_psrldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_undefined_epi32 (),\ + (__mmask16)-1)) + +#define _mm512_mask_srli_epi32(W, U, X, C) \ + ((__m512i) __builtin_ia32_psrldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)(W), \ + (__mmask16)(U))) + +#define _mm512_maskz_srli_epi32(U, X, C) \ + ((__m512i) __builtin_ia32_psrldi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_setzero_si512 (), \ + (__mmask16)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srl_epi32 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srl_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srl_epi32 (__mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_srai_epi32 (__m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psradi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_srai_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + unsigned int __B) +{ + return (__m512i) __builtin_ia32_psradi512_mask ((__v16si) __A, __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_srai_epi32 (__mmask16 __U, __m512i __A, unsigned int __B) +{ + return (__m512i) __builtin_ia32_psradi512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} +#else +#define _mm512_srai_epi32(X, C) \ + ((__m512i) __builtin_ia32_psradi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_undefined_epi32 (),\ + (__mmask16)-1)) + +#define _mm512_mask_srai_epi32(W, U, X, C) \ + ((__m512i) __builtin_ia32_psradi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)(W), \ + (__mmask16)(U))) + +#define _mm512_maskz_srai_epi32(U, X, C) \ + ((__m512i) __builtin_ia32_psradi512_mask ((__v16si)(__m512i)(X), \ + (unsigned int)(C), \ + (__v16si)(__m512i)_mm512_setzero_si512 (), \ + (__mmask16)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sra_epi32 (__m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sra_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sra_epi32 (__mmask16 __U, __m512i __A, __m128i __B) +{ + return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A, + (__v4si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +/* Constant helper to represent the ternary logic operations among + vector A, B and C. */ +typedef enum +{ + _MM_TERNLOG_A = 0xF0, + _MM_TERNLOG_B = 0xCC, + _MM_TERNLOG_C = 0xAA +} _MM_TERNLOG_ENUM; + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ternarylogic_epi64 (__m512i __A, __m512i __B, __m512i __C, + const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __C, + (unsigned char) __imm, + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ternarylogic_epi64 (__m512i __A, __mmask8 __U, __m512i __B, + __m512i __C, const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_ternarylogic_epi64 (__mmask8 __U, __m512i __A, __m512i __B, + __m512i __C, const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogq512_maskz ((__v8di) __A, + (__v8di) __B, + (__v8di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ternarylogic_epi32 (__m512i __A, __m512i __B, __m512i __C, + const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __C, + (unsigned char) __imm, + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ternarylogic_epi32 (__m512i __A, __mmask16 __U, __m512i __B, + __m512i __C, const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __C, + (unsigned char) __imm, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_ternarylogic_epi32 (__mmask16 __U, __m512i __A, __m512i __B, + __m512i __C, const int __imm) +{ + return (__m512i) + __builtin_ia32_pternlogd512_maskz ((__v16si) __A, + (__v16si) __B, + (__v16si) __C, + (unsigned char) __imm, + (__mmask16) __U); +} +#else +#define _mm512_ternarylogic_epi64(A, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogq512_mask ((__v8di) (__m512i) (A), \ + (__v8di) (__m512i) (B), \ + (__v8di) (__m512i) (C), \ + (unsigned char) (I), \ + (__mmask8) -1)) +#define _mm512_mask_ternarylogic_epi64(A, U, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogq512_mask ((__v8di) (__m512i) (A), \ + (__v8di) (__m512i) (B), \ + (__v8di) (__m512i) (C), \ + (unsigned char)(I), \ + (__mmask8) (U))) +#define _mm512_maskz_ternarylogic_epi64(U, A, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogq512_maskz ((__v8di) (__m512i) (A), \ + (__v8di) (__m512i) (B), \ + (__v8di) (__m512i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) +#define _mm512_ternarylogic_epi32(A, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogd512_mask ((__v16si) (__m512i) (A), \ + (__v16si) (__m512i) (B), \ + (__v16si) (__m512i) (C), \ + (unsigned char) (I), \ + (__mmask16) -1)) +#define _mm512_mask_ternarylogic_epi32(A, U, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogd512_mask ((__v16si) (__m512i) (A), \ + (__v16si) (__m512i) (B), \ + (__v16si) (__m512i) (C), \ + (unsigned char) (I), \ + (__mmask16) (U))) +#define _mm512_maskz_ternarylogic_epi32(U, A, B, C, I) \ + ((__m512i) \ + __builtin_ia32_pternlogd512_maskz ((__v16si) (__m512i) (A), \ + (__v16si) (__m512i) (B), \ + (__v16si) (__m512i) (C), \ + (unsigned char) (I), \ + (__mmask16) (U))) +#endif + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rcp14_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rcp14_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rcp14_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rcp14_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rcp14_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rcp14_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rsqrt14_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rsqrt14_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rsqrt14_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rsqrt14_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rsqrt14_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rsqrt14_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_round_pd (__m512d __A, const int __R) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_round_pd (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_round_ps (__m512 __A, const int __R) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_round_ps (__m512 __W, __mmask16 __U, __m512 __A, const int __R) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_round_ps (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +#else +#define _mm512_sqrt_round_pd(A, C) \ + (__m512d)__builtin_ia32_sqrtpd512_mask(A, (__v8df)_mm512_undefined_pd(), -1, C) + +#define _mm512_mask_sqrt_round_pd(W, U, A, C) \ + (__m512d)__builtin_ia32_sqrtpd512_mask(A, W, U, C) + +#define _mm512_maskz_sqrt_round_pd(U, A, C) \ + (__m512d)__builtin_ia32_sqrtpd512_mask(A, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_sqrt_round_ps(A, C) \ + (__m512)__builtin_ia32_sqrtps512_mask(A, (__v16sf)_mm512_undefined_ps(), -1, C) + +#define _mm512_mask_sqrt_round_ps(W, U, A, C) \ + (__m512)__builtin_ia32_sqrtps512_mask(A, W, U, C) + +#define _mm512_maskz_sqrt_round_ps(U, A, C) \ + (__m512)__builtin_ia32_sqrtps512_mask(A, (__v16sf)_mm512_setzero_ps(), U, C) + +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi8_epi32 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi8_epi32 (__m512i __W, __mmask16 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi8_epi32 (__mmask16 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi8_epi64 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi8_epi64 (__m512i __W, __mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi16_epi32 (__m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi16_epi32 (__m512i __W, __mmask16 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi16_epi32 (__mmask16 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi16_epi64 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi16_epi64 (__m512i __W, __mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_epi64 (__m256i __X) +{ + return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_epi64 (__m512i __W, __mmask8 __U, __m256i __X) +{ + return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_epi64 (__mmask8 __U, __m256i __X) +{ + return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu8_epi32 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu8_epi32 (__m512i __W, __mmask16 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu8_epi32 (__mmask16 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu8_epi64 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu8_epi64 (__m512i __W, __mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu16_epi32 (__m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu16_epi32 (__m512i __W, __mmask16 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu16_epi32 (__mmask16 __U, __m256i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu16_epi64 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu16_epi64 (__m512i __W, __mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu32_epi64 (__m256i __X) +{ + return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu32_epi64 (__m512i __W, __mmask8 __U, __m256i __X) +{ + return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu32_epi64 (__mmask8 __U, __m256i __X) +{ + return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} +#else +#define _mm512_add_round_pd(A, B, C) \ + (__m512d)__builtin_ia32_addpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, C) + +#define _mm512_mask_add_round_pd(W, U, A, B, C) \ + (__m512d)__builtin_ia32_addpd512_mask(A, B, W, U, C) + +#define _mm512_maskz_add_round_pd(U, A, B, C) \ + (__m512d)__builtin_ia32_addpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_add_round_ps(A, B, C) \ + (__m512)__builtin_ia32_addps512_mask(A, B, (__v16sf)_mm512_undefined_ps(), -1, C) + +#define _mm512_mask_add_round_ps(W, U, A, B, C) \ + (__m512)__builtin_ia32_addps512_mask(A, B, W, U, C) + +#define _mm512_maskz_add_round_ps(U, A, B, C) \ + (__m512)__builtin_ia32_addps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, C) + +#define _mm512_sub_round_pd(A, B, C) \ + (__m512d)__builtin_ia32_subpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, C) + +#define _mm512_mask_sub_round_pd(W, U, A, B, C) \ + (__m512d)__builtin_ia32_subpd512_mask(A, B, W, U, C) + +#define _mm512_maskz_sub_round_pd(U, A, B, C) \ + (__m512d)__builtin_ia32_subpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_sub_round_ps(A, B, C) \ + (__m512)__builtin_ia32_subps512_mask(A, B, (__v16sf)_mm512_undefined_ps(), -1, C) + +#define _mm512_mask_sub_round_ps(W, U, A, B, C) \ + (__m512)__builtin_ia32_subps512_mask(A, B, W, U, C) + +#define _mm512_maskz_sub_round_ps(U, A, B, C) \ + (__m512)__builtin_ia32_subps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, C) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_round_pd (__m512d __M, __m512d __V, const int __R) +{ + return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __M, + (__v8df) __V, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_round_pd (__m512d __W, __mmask8 __U, __m512d __M, + __m512d __V, const int __R) +{ + return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __M, + (__v8df) __V, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_round_pd (__mmask8 __U, __m512d __M, __m512d __V, + const int __R) +{ + return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __M, + (__v8df) __V, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +#else +#define _mm512_mul_round_pd(A, B, C) \ + (__m512d)__builtin_ia32_mulpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, C) + +#define _mm512_mask_mul_round_pd(W, U, A, B, C) \ + (__m512d)__builtin_ia32_mulpd512_mask(A, B, W, U, C) + +#define _mm512_maskz_mul_round_pd(U, A, B, C) \ + (__m512d)__builtin_ia32_mulpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_mul_round_ps(A, B, C) \ + (__m512)__builtin_ia32_mulps512_mask(A, B, (__v16sf)_mm512_undefined_ps(), -1, C) + +#define _mm512_mask_mul_round_ps(W, U, A, B, C) \ + (__m512)__builtin_ia32_mulps512_mask(A, B, W, U, C) + +#define _mm512_maskz_mul_round_ps(U, A, B, C) \ + (__m512)__builtin_ia32_mulps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, C) + +#define _mm512_div_round_pd(A, B, C) \ + (__m512d)__builtin_ia32_divpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, C) + +#define _mm512_mask_div_round_pd(W, U, A, B, C) \ + (__m512d)__builtin_ia32_divpd512_mask(A, B, W, U, C) + +#define _mm512_maskz_div_round_pd(U, A, B, C) \ + (__m512d)__builtin_ia32_divpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, C) + +#define _mm512_div_round_ps(A, B, C) \ + (__m512)__builtin_ia32_divps512_mask(A, B, (__v16sf)_mm512_undefined_ps(), -1, C) + +#define _mm512_mask_div_round_ps(W, U, A, B, C) \ + (__m512)__builtin_ia32_divps512_mask(A, B, W, U, C) + +#define _mm512_maskz_div_round_ps(U, A, B, C) \ + (__m512)__builtin_ia32_divps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, C) + +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_round_ps (__mmask16 __U, __m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} +#else +#define _mm512_max_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_maxpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, R) + +#define _mm512_mask_max_round_pd(W, U, A, B, R) \ + (__m512d)__builtin_ia32_maxpd512_mask(A, B, W, U, R) + +#define _mm512_maskz_max_round_pd(U, A, B, R) \ + (__m512d)__builtin_ia32_maxpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, R) + +#define _mm512_max_round_ps(A, B, R) \ + (__m512)__builtin_ia32_maxps512_mask(A, B, (__v16sf)_mm512_undefined_pd(), -1, R) + +#define _mm512_mask_max_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_maxps512_mask(A, B, W, U, R) + +#define _mm512_maskz_max_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_maxps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, R) + +#define _mm512_min_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_minpd512_mask(A, B, (__v8df)_mm512_undefined_pd(), -1, R) + +#define _mm512_mask_min_round_pd(W, U, A, B, R) \ + (__m512d)__builtin_ia32_minpd512_mask(A, B, W, U, R) + +#define _mm512_maskz_min_round_pd(U, A, B, R) \ + (__m512d)__builtin_ia32_minpd512_mask(A, B, (__v8df)_mm512_setzero_pd(), U, R) + +#define _mm512_min_round_ps(A, B, R) \ + (__m512)__builtin_ia32_minps512_mask(A, B, (__v16sf)_mm512_undefined_ps(), -1, R) + +#define _mm512_mask_min_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_minps512_mask(A, B, W, U, R) + +#define _mm512_maskz_min_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_minps512_mask(A, B, (__v16sf)_mm512_setzero_ps(), U, R) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_round_pd (__m512d __A, __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __R) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + const int __R) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_round_ps (__m512 __A, __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __R) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + const int __R) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +#else +#define _mm512_scalef_round_pd(A, B, C) \ + ((__m512d) \ + __builtin_ia32_scalefpd512_mask((A), (B), \ + (__v8df) _mm512_undefined_pd(), \ + -1, (C))) + +#define _mm512_mask_scalef_round_pd(W, U, A, B, C) \ + ((__m512d) __builtin_ia32_scalefpd512_mask((A), (B), (W), (U), (C))) + +#define _mm512_maskz_scalef_round_pd(U, A, B, C) \ + ((__m512d) \ + __builtin_ia32_scalefpd512_mask((A), (B), \ + (__v8df) _mm512_setzero_pd(), \ + (U), (C))) + +#define _mm512_scalef_round_ps(A, B, C) \ + ((__m512) \ + __builtin_ia32_scalefps512_mask((A), (B), \ + (__v16sf) _mm512_undefined_ps(), \ + -1, (C))) + +#define _mm512_mask_scalef_round_ps(W, U, A, B, C) \ + ((__m512) __builtin_ia32_scalefps512_mask((A), (B), (W), (U), (C))) + +#define _mm512_maskz_scalef_round_ps(U, A, B, C) \ + ((__m512) \ + __builtin_ia32_scalefps512_mask((A), (B), \ + (__v16sf) _mm512_setzero_ps(), \ + (U), (C))) + +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsubadd_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsubadd_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_round_pd (__m512d __A, __m512d __B, __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_round_pd (__m512d __A, __m512d __B, __m512d __C, + __mmask8 __U, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512d __C, const int __R) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_round_ps (__m512 __A, __m512 __B, __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_round_ps (__m512 __A, __m512 __B, __m512 __C, + __mmask16 __U, const int __R) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512 __C, const int __R) +{ + return (__m512) __builtin_ia32_vfnmsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, __R); +} +#else +#define _mm512_fmadd_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddpd512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmadd_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddpd512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmadd_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfmaddpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmadd_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddpd512_maskz(A, B, C, U, R) + +#define _mm512_fmadd_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddps512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmadd_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfmaddps512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmadd_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfmaddps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmadd_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddps512_maskz(A, B, C, U, R) + +#define _mm512_fmsub_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfmsubpd512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmsub_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfmsubpd512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmsub_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfmsubpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmsub_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfmsubpd512_maskz(A, B, C, U, R) + +#define _mm512_fmsub_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfmsubps512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmsub_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfmsubps512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmsub_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfmsubps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmsub_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfmsubps512_maskz(A, B, C, U, R) + +#define _mm512_fmaddsub_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmaddsub_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmaddsub_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmaddsub_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_maskz(A, B, C, U, R) + +#define _mm512_fmaddsub_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_mask(A, B, C, -1, R) + +#define _mm512_mask_fmaddsub_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_mask(A, B, C, U, R) + +#define _mm512_mask3_fmaddsub_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmaddsub_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_maskz(A, B, C, U, R) + +#define _mm512_fmsubadd_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_mask(A, B, -(C), -1, R) + +#define _mm512_mask_fmsubadd_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_mask(A, B, -(C), U, R) + +#define _mm512_mask3_fmsubadd_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfmsubaddpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmsubadd_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfmaddsubpd512_maskz(A, B, -(C), U, R) + +#define _mm512_fmsubadd_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_mask(A, B, -(C), -1, R) + +#define _mm512_mask_fmsubadd_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_mask(A, B, -(C), U, R) + +#define _mm512_mask3_fmsubadd_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfmsubaddps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fmsubadd_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfmaddsubps512_maskz(A, B, -(C), U, R) + +#define _mm512_fnmadd_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfnmaddpd512_mask(A, B, C, -1, R) + +#define _mm512_mask_fnmadd_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfnmaddpd512_mask(A, B, C, U, R) + +#define _mm512_mask3_fnmadd_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfnmaddpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fnmadd_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfnmaddpd512_maskz(A, B, C, U, R) + +#define _mm512_fnmadd_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfnmaddps512_mask(A, B, C, -1, R) + +#define _mm512_mask_fnmadd_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfnmaddps512_mask(A, B, C, U, R) + +#define _mm512_mask3_fnmadd_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfnmaddps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fnmadd_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfnmaddps512_maskz(A, B, C, U, R) + +#define _mm512_fnmsub_round_pd(A, B, C, R) \ + (__m512d)__builtin_ia32_vfnmsubpd512_mask(A, B, C, -1, R) + +#define _mm512_mask_fnmsub_round_pd(A, U, B, C, R) \ + (__m512d)__builtin_ia32_vfnmsubpd512_mask(A, B, C, U, R) + +#define _mm512_mask3_fnmsub_round_pd(A, B, C, U, R) \ + (__m512d)__builtin_ia32_vfnmsubpd512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fnmsub_round_pd(U, A, B, C, R) \ + (__m512d)__builtin_ia32_vfnmsubpd512_maskz(A, B, C, U, R) + +#define _mm512_fnmsub_round_ps(A, B, C, R) \ + (__m512)__builtin_ia32_vfnmsubps512_mask(A, B, C, -1, R) + +#define _mm512_mask_fnmsub_round_ps(A, U, B, C, R) \ + (__m512)__builtin_ia32_vfnmsubps512_mask(A, B, C, U, R) + +#define _mm512_mask3_fnmsub_round_ps(A, B, C, U, R) \ + (__m512)__builtin_ia32_vfnmsubps512_mask3(A, B, C, U, R) + +#define _mm512_maskz_fnmsub_round_ps(U, A, B, C, R) \ + (__m512)__builtin_ia32_vfnmsubps512_maskz(A, B, C, U, R) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_epi64 (__m512i __A) +{ + return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_abs_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_epi32 (__m512i __A) +{ + return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_abs_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastss_ps (__m128 __A) +{ + return (__m512) __builtin_ia32_broadcastss512 ((__v4sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastss_ps (__m512 __O, __mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastss512 ((__v4sf) __A, + (__v16sf) __O, __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastss_ps (__mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastss512 ((__v4sf) __A, + (__v16sf) + _mm512_setzero_ps (), + __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastsd_pd (__m128d __A) +{ + return (__m512d) __builtin_ia32_broadcastsd512 ((__v2df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastsd_pd (__m512d __O, __mmask8 __M, __m128d __A) +{ + return (__m512d) __builtin_ia32_broadcastsd512 ((__v2df) __A, + (__v8df) __O, __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) +{ + return (__m512d) __builtin_ia32_broadcastsd512 ((__v2df) __A, + (__v8df) + _mm512_setzero_pd (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastd_epi32 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastd512 ((__v4si) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastd_epi32 (__m512i __O, __mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastd512 ((__v4si) __A, + (__v16si) __O, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastd512 ((__v4si) __A, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_epi32 (int __A) +{ + return (__m512i)(__v16si) + { __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A) +{ + return (__m512i) __builtin_ia32_pbroadcastd512_gpr_mask (__A, (__v16si) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_set1_epi32 (__mmask16 __M, int __A) +{ + return (__m512i) + __builtin_ia32_pbroadcastd512_gpr_mask (__A, + (__v16si) _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcastq_epi64 (__m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastq512 ((__v2di) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcastq_epi64 (__m512i __O, __mmask8 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastq512 ((__v2di) __A, + (__v8di) __O, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_pbroadcastq512 ((__v2di) __A, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_epi64 (long long __A) +{ + return (__m512i)(__v8di) { __A, __A, __A, __A, __A, __A, __A, __A }; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A) +{ + return (__m512i) __builtin_ia32_pbroadcastq512_gpr_mask (__A, (__v8di) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_set1_epi64 (__mmask8 __M, long long __A) +{ + return (__m512i) + __builtin_ia32_pbroadcastq512_gpr_mask (__A, + (__v8di) _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_f32x4 (__m128 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x4_512 ((__v4sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_f32x4 (__m512 __O, __mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x4_512 ((__v4sf) __A, + (__v16sf) __O, + __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_f32x4 (__mmask16 __M, __m128 __A) +{ + return (__m512) __builtin_ia32_broadcastf32x4_512 ((__v4sf) __A, + (__v16sf) + _mm512_setzero_ps (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_i32x4 (__m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x4_512 ((__v4si) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_i32x4 (__m512i __O, __mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x4_512 ((__v4si) __A, + (__v16si) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_i32x4 (__mmask16 __M, __m128i __A) +{ + return (__m512i) __builtin_ia32_broadcasti32x4_512 ((__v4si) __A, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_f64x4 (__m256d __A) +{ + return (__m512d) __builtin_ia32_broadcastf64x4_512 ((__v4df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_f64x4 (__m512d __O, __mmask8 __M, __m256d __A) +{ + return (__m512d) __builtin_ia32_broadcastf64x4_512 ((__v4df) __A, + (__v8df) __O, + __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_f64x4 (__mmask8 __M, __m256d __A) +{ + return (__m512d) __builtin_ia32_broadcastf64x4_512 ((__v4df) __A, + (__v8df) + _mm512_setzero_pd (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_broadcast_i64x4 (__m256i __A) +{ + return (__m512i) __builtin_ia32_broadcasti64x4_512 ((__v4di) __A, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_broadcast_i64x4 (__m512i __O, __mmask8 __M, __m256i __A) +{ + return (__m512i) __builtin_ia32_broadcasti64x4_512 ((__v4di) __A, + (__v8di) __O, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_broadcast_i64x4 (__mmask8 __M, __m256i __A) +{ + return (__m512i) __builtin_ia32_broadcasti64x4_512 ((__v4di) __A, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +typedef enum +{ + _MM_PERM_AAAA = 0x00, _MM_PERM_AAAB = 0x01, _MM_PERM_AAAC = 0x02, + _MM_PERM_AAAD = 0x03, _MM_PERM_AABA = 0x04, _MM_PERM_AABB = 0x05, + _MM_PERM_AABC = 0x06, _MM_PERM_AABD = 0x07, _MM_PERM_AACA = 0x08, + _MM_PERM_AACB = 0x09, _MM_PERM_AACC = 0x0A, _MM_PERM_AACD = 0x0B, + _MM_PERM_AADA = 0x0C, _MM_PERM_AADB = 0x0D, _MM_PERM_AADC = 0x0E, + _MM_PERM_AADD = 0x0F, _MM_PERM_ABAA = 0x10, _MM_PERM_ABAB = 0x11, + _MM_PERM_ABAC = 0x12, _MM_PERM_ABAD = 0x13, _MM_PERM_ABBA = 0x14, + _MM_PERM_ABBB = 0x15, _MM_PERM_ABBC = 0x16, _MM_PERM_ABBD = 0x17, + _MM_PERM_ABCA = 0x18, _MM_PERM_ABCB = 0x19, _MM_PERM_ABCC = 0x1A, + _MM_PERM_ABCD = 0x1B, _MM_PERM_ABDA = 0x1C, _MM_PERM_ABDB = 0x1D, + _MM_PERM_ABDC = 0x1E, _MM_PERM_ABDD = 0x1F, _MM_PERM_ACAA = 0x20, + _MM_PERM_ACAB = 0x21, _MM_PERM_ACAC = 0x22, _MM_PERM_ACAD = 0x23, + _MM_PERM_ACBA = 0x24, _MM_PERM_ACBB = 0x25, _MM_PERM_ACBC = 0x26, + _MM_PERM_ACBD = 0x27, _MM_PERM_ACCA = 0x28, _MM_PERM_ACCB = 0x29, + _MM_PERM_ACCC = 0x2A, _MM_PERM_ACCD = 0x2B, _MM_PERM_ACDA = 0x2C, + _MM_PERM_ACDB = 0x2D, _MM_PERM_ACDC = 0x2E, _MM_PERM_ACDD = 0x2F, + _MM_PERM_ADAA = 0x30, _MM_PERM_ADAB = 0x31, _MM_PERM_ADAC = 0x32, + _MM_PERM_ADAD = 0x33, _MM_PERM_ADBA = 0x34, _MM_PERM_ADBB = 0x35, + _MM_PERM_ADBC = 0x36, _MM_PERM_ADBD = 0x37, _MM_PERM_ADCA = 0x38, + _MM_PERM_ADCB = 0x39, _MM_PERM_ADCC = 0x3A, _MM_PERM_ADCD = 0x3B, + _MM_PERM_ADDA = 0x3C, _MM_PERM_ADDB = 0x3D, _MM_PERM_ADDC = 0x3E, + _MM_PERM_ADDD = 0x3F, _MM_PERM_BAAA = 0x40, _MM_PERM_BAAB = 0x41, + _MM_PERM_BAAC = 0x42, _MM_PERM_BAAD = 0x43, _MM_PERM_BABA = 0x44, + _MM_PERM_BABB = 0x45, _MM_PERM_BABC = 0x46, _MM_PERM_BABD = 0x47, + _MM_PERM_BACA = 0x48, _MM_PERM_BACB = 0x49, _MM_PERM_BACC = 0x4A, + _MM_PERM_BACD = 0x4B, _MM_PERM_BADA = 0x4C, _MM_PERM_BADB = 0x4D, + _MM_PERM_BADC = 0x4E, _MM_PERM_BADD = 0x4F, _MM_PERM_BBAA = 0x50, + _MM_PERM_BBAB = 0x51, _MM_PERM_BBAC = 0x52, _MM_PERM_BBAD = 0x53, + _MM_PERM_BBBA = 0x54, _MM_PERM_BBBB = 0x55, _MM_PERM_BBBC = 0x56, + _MM_PERM_BBBD = 0x57, _MM_PERM_BBCA = 0x58, _MM_PERM_BBCB = 0x59, + _MM_PERM_BBCC = 0x5A, _MM_PERM_BBCD = 0x5B, _MM_PERM_BBDA = 0x5C, + _MM_PERM_BBDB = 0x5D, _MM_PERM_BBDC = 0x5E, _MM_PERM_BBDD = 0x5F, + _MM_PERM_BCAA = 0x60, _MM_PERM_BCAB = 0x61, _MM_PERM_BCAC = 0x62, + _MM_PERM_BCAD = 0x63, _MM_PERM_BCBA = 0x64, _MM_PERM_BCBB = 0x65, + _MM_PERM_BCBC = 0x66, _MM_PERM_BCBD = 0x67, _MM_PERM_BCCA = 0x68, + _MM_PERM_BCCB = 0x69, _MM_PERM_BCCC = 0x6A, _MM_PERM_BCCD = 0x6B, + _MM_PERM_BCDA = 0x6C, _MM_PERM_BCDB = 0x6D, _MM_PERM_BCDC = 0x6E, + _MM_PERM_BCDD = 0x6F, _MM_PERM_BDAA = 0x70, _MM_PERM_BDAB = 0x71, + _MM_PERM_BDAC = 0x72, _MM_PERM_BDAD = 0x73, _MM_PERM_BDBA = 0x74, + _MM_PERM_BDBB = 0x75, _MM_PERM_BDBC = 0x76, _MM_PERM_BDBD = 0x77, + _MM_PERM_BDCA = 0x78, _MM_PERM_BDCB = 0x79, _MM_PERM_BDCC = 0x7A, + _MM_PERM_BDCD = 0x7B, _MM_PERM_BDDA = 0x7C, _MM_PERM_BDDB = 0x7D, + _MM_PERM_BDDC = 0x7E, _MM_PERM_BDDD = 0x7F, _MM_PERM_CAAA = 0x80, + _MM_PERM_CAAB = 0x81, _MM_PERM_CAAC = 0x82, _MM_PERM_CAAD = 0x83, + _MM_PERM_CABA = 0x84, _MM_PERM_CABB = 0x85, _MM_PERM_CABC = 0x86, + _MM_PERM_CABD = 0x87, _MM_PERM_CACA = 0x88, _MM_PERM_CACB = 0x89, + _MM_PERM_CACC = 0x8A, _MM_PERM_CACD = 0x8B, _MM_PERM_CADA = 0x8C, + _MM_PERM_CADB = 0x8D, _MM_PERM_CADC = 0x8E, _MM_PERM_CADD = 0x8F, + _MM_PERM_CBAA = 0x90, _MM_PERM_CBAB = 0x91, _MM_PERM_CBAC = 0x92, + _MM_PERM_CBAD = 0x93, _MM_PERM_CBBA = 0x94, _MM_PERM_CBBB = 0x95, + _MM_PERM_CBBC = 0x96, _MM_PERM_CBBD = 0x97, _MM_PERM_CBCA = 0x98, + _MM_PERM_CBCB = 0x99, _MM_PERM_CBCC = 0x9A, _MM_PERM_CBCD = 0x9B, + _MM_PERM_CBDA = 0x9C, _MM_PERM_CBDB = 0x9D, _MM_PERM_CBDC = 0x9E, + _MM_PERM_CBDD = 0x9F, _MM_PERM_CCAA = 0xA0, _MM_PERM_CCAB = 0xA1, + _MM_PERM_CCAC = 0xA2, _MM_PERM_CCAD = 0xA3, _MM_PERM_CCBA = 0xA4, + _MM_PERM_CCBB = 0xA5, _MM_PERM_CCBC = 0xA6, _MM_PERM_CCBD = 0xA7, + _MM_PERM_CCCA = 0xA8, _MM_PERM_CCCB = 0xA9, _MM_PERM_CCCC = 0xAA, + _MM_PERM_CCCD = 0xAB, _MM_PERM_CCDA = 0xAC, _MM_PERM_CCDB = 0xAD, + _MM_PERM_CCDC = 0xAE, _MM_PERM_CCDD = 0xAF, _MM_PERM_CDAA = 0xB0, + _MM_PERM_CDAB = 0xB1, _MM_PERM_CDAC = 0xB2, _MM_PERM_CDAD = 0xB3, + _MM_PERM_CDBA = 0xB4, _MM_PERM_CDBB = 0xB5, _MM_PERM_CDBC = 0xB6, + _MM_PERM_CDBD = 0xB7, _MM_PERM_CDCA = 0xB8, _MM_PERM_CDCB = 0xB9, + _MM_PERM_CDCC = 0xBA, _MM_PERM_CDCD = 0xBB, _MM_PERM_CDDA = 0xBC, + _MM_PERM_CDDB = 0xBD, _MM_PERM_CDDC = 0xBE, _MM_PERM_CDDD = 0xBF, + _MM_PERM_DAAA = 0xC0, _MM_PERM_DAAB = 0xC1, _MM_PERM_DAAC = 0xC2, + _MM_PERM_DAAD = 0xC3, _MM_PERM_DABA = 0xC4, _MM_PERM_DABB = 0xC5, + _MM_PERM_DABC = 0xC6, _MM_PERM_DABD = 0xC7, _MM_PERM_DACA = 0xC8, + _MM_PERM_DACB = 0xC9, _MM_PERM_DACC = 0xCA, _MM_PERM_DACD = 0xCB, + _MM_PERM_DADA = 0xCC, _MM_PERM_DADB = 0xCD, _MM_PERM_DADC = 0xCE, + _MM_PERM_DADD = 0xCF, _MM_PERM_DBAA = 0xD0, _MM_PERM_DBAB = 0xD1, + _MM_PERM_DBAC = 0xD2, _MM_PERM_DBAD = 0xD3, _MM_PERM_DBBA = 0xD4, + _MM_PERM_DBBB = 0xD5, _MM_PERM_DBBC = 0xD6, _MM_PERM_DBBD = 0xD7, + _MM_PERM_DBCA = 0xD8, _MM_PERM_DBCB = 0xD9, _MM_PERM_DBCC = 0xDA, + _MM_PERM_DBCD = 0xDB, _MM_PERM_DBDA = 0xDC, _MM_PERM_DBDB = 0xDD, + _MM_PERM_DBDC = 0xDE, _MM_PERM_DBDD = 0xDF, _MM_PERM_DCAA = 0xE0, + _MM_PERM_DCAB = 0xE1, _MM_PERM_DCAC = 0xE2, _MM_PERM_DCAD = 0xE3, + _MM_PERM_DCBA = 0xE4, _MM_PERM_DCBB = 0xE5, _MM_PERM_DCBC = 0xE6, + _MM_PERM_DCBD = 0xE7, _MM_PERM_DCCA = 0xE8, _MM_PERM_DCCB = 0xE9, + _MM_PERM_DCCC = 0xEA, _MM_PERM_DCCD = 0xEB, _MM_PERM_DCDA = 0xEC, + _MM_PERM_DCDB = 0xED, _MM_PERM_DCDC = 0xEE, _MM_PERM_DCDD = 0xEF, + _MM_PERM_DDAA = 0xF0, _MM_PERM_DDAB = 0xF1, _MM_PERM_DDAC = 0xF2, + _MM_PERM_DDAD = 0xF3, _MM_PERM_DDBA = 0xF4, _MM_PERM_DDBB = 0xF5, + _MM_PERM_DDBC = 0xF6, _MM_PERM_DDBD = 0xF7, _MM_PERM_DDCA = 0xF8, + _MM_PERM_DDCB = 0xF9, _MM_PERM_DDCC = 0xFA, _MM_PERM_DDCD = 0xFB, + _MM_PERM_DDDA = 0xFC, _MM_PERM_DDDB = 0xFD, _MM_PERM_DDDC = 0xFE, + _MM_PERM_DDDD = 0xFF +} _MM_PERM_ENUM; + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_epi32 (__m512i __A, _MM_PERM_ENUM __mask) +{ + return (__m512i) __builtin_ia32_pshufd512_mask ((__v16si) __A, + __mask, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + _MM_PERM_ENUM __mask) +{ + return (__m512i) __builtin_ia32_pshufd512_mask ((__v16si) __A, + __mask, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_epi32 (__mmask16 __U, __m512i __A, _MM_PERM_ENUM __mask) +{ + return (__m512i) __builtin_ia32_pshufd512_mask ((__v16si) __A, + __mask, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_i64x2 (__m512i __A, __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_i64x2 (__m512i __W, __mmask8 __U, __m512i __A, + __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_i64x2 (__mmask8 __U, __m512i __A, __m512i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_i32x4 (__m512i __A, __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si) __A, + (__v16si) __B, + __imm, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_i32x4 (__m512i __W, __mmask16 __U, __m512i __A, + __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si) __A, + (__v16si) __B, + __imm, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_i32x4 (__mmask16 __U, __m512i __A, __m512i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si) __A, + (__v16si) __B, + __imm, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_f64x2 (__m512d __A, __m512d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df) __A, + (__v8df) __B, __imm, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_f64x2 (__m512d __W, __mmask8 __U, __m512d __A, + __m512d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df) __A, + (__v8df) __B, __imm, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_f64x2 (__mmask8 __U, __m512d __A, __m512d __B, + const int __imm) +{ + return (__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df) __A, + (__v8df) __B, __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_f32x4 (__m512 __A, __m512 __B, const int __imm) +{ + return (__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf) __A, + (__v16sf) __B, __imm, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_f32x4 (__m512 __W, __mmask16 __U, __m512 __A, + __m512 __B, const int __imm) +{ + return (__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf) __A, + (__v16sf) __B, __imm, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_f32x4 (__mmask16 __U, __m512 __A, __m512 __B, + const int __imm) +{ + return (__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf) __A, + (__v16sf) __B, __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +#else +#define _mm512_shuffle_epi32(X, C) \ + ((__m512i) __builtin_ia32_pshufd512_mask ((__v16si)(__m512i)(X), (int)(C),\ + (__v16si)(__m512i)_mm512_undefined_epi32 (),\ + (__mmask16)-1)) + +#define _mm512_mask_shuffle_epi32(W, U, X, C) \ + ((__m512i) __builtin_ia32_pshufd512_mask ((__v16si)(__m512i)(X), (int)(C),\ + (__v16si)(__m512i)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_shuffle_epi32(U, X, C) \ + ((__m512i) __builtin_ia32_pshufd512_mask ((__v16si)(__m512i)(X), (int)(C),\ + (__v16si)(__m512i)_mm512_setzero_si512 (),\ + (__mmask16)(U))) + +#define _mm512_shuffle_i64x2(X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C),\ + (__v8di)(__m512i)_mm512_undefined_epi32 (),\ + (__mmask8)-1)) + +#define _mm512_mask_shuffle_i64x2(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C),\ + (__v8di)(__m512i)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_shuffle_i64x2(U, X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i64x2_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C),\ + (__v8di)(__m512i)_mm512_setzero_si512 (),\ + (__mmask8)(U))) + +#define _mm512_shuffle_i32x4(X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C),\ + (__v16si)(__m512i)_mm512_undefined_epi32 (),\ + (__mmask16)-1)) + +#define _mm512_mask_shuffle_i32x4(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C),\ + (__v16si)(__m512i)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_shuffle_i32x4(U, X, Y, C) \ + ((__m512i) __builtin_ia32_shuf_i32x4_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C),\ + (__v16si)(__m512i)_mm512_setzero_si512 (),\ + (__mmask16)(U))) + +#define _mm512_shuffle_f64x2(X, Y, C) \ + ((__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)_mm512_undefined_pd(),\ + (__mmask8)-1)) + +#define _mm512_mask_shuffle_f64x2(W, U, X, Y, C) \ + ((__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_shuffle_f64x2(U, X, Y, C) \ + ((__m512d) __builtin_ia32_shuf_f64x2_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)_mm512_setzero_pd(),\ + (__mmask8)(U))) + +#define _mm512_shuffle_f32x4(X, Y, C) \ + ((__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)_mm512_undefined_ps(),\ + (__mmask16)-1)) + +#define _mm512_mask_shuffle_f32x4(W, U, X, Y, C) \ + ((__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_shuffle_f32x4(U, X, Y, C) \ + ((__m512) __builtin_ia32_shuf_f32x4_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)_mm512_setzero_ps(),\ + (__mmask16)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rolv_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rolv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rolv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rorv_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rorv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rorv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rolv_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rolv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rorv_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rorv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundpd_epi32 (__m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundpd_epi32 (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundpd_epu32 (__m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundpd_epu32 (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, __R); +} +#else +#define _mm512_cvtt_roundpd_epi32(A, B) \ + ((__m256i)__builtin_ia32_cvttpd2dq512_mask(A, (__v8si)_mm256_undefined_si256(), -1, B)) + +#define _mm512_mask_cvtt_roundpd_epi32(W, U, A, B) \ + ((__m256i)__builtin_ia32_cvttpd2dq512_mask(A, (__v8si)(W), U, B)) + +#define _mm512_maskz_cvtt_roundpd_epi32(U, A, B) \ + ((__m256i)__builtin_ia32_cvttpd2dq512_mask(A, (__v8si)_mm256_setzero_si256(), U, B)) + +#define _mm512_cvtt_roundpd_epu32(A, B) \ + ((__m256i)__builtin_ia32_cvttpd2udq512_mask(A, (__v8si)_mm256_undefined_si256(), -1, B)) + +#define _mm512_mask_cvtt_roundpd_epu32(W, U, A, B) \ + ((__m256i)__builtin_ia32_cvttpd2udq512_mask(A, (__v8si)(W), U, B)) + +#define _mm512_maskz_cvtt_roundpd_epu32(U, A, B) \ + ((__m256i)__builtin_ia32_cvttpd2udq512_mask(A, (__v8si)_mm256_setzero_si256(), U, B)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_epi32 (__m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_epi32 (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_epu32 (__m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_epu32 (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, __R); +} +#else +#define _mm512_cvt_roundpd_epi32(A, B) \ + ((__m256i)__builtin_ia32_cvtpd2dq512_mask(A, (__v8si)_mm256_undefined_si256(), -1, B)) + +#define _mm512_mask_cvt_roundpd_epi32(W, U, A, B) \ + ((__m256i)__builtin_ia32_cvtpd2dq512_mask(A, (__v8si)(W), U, B)) + +#define _mm512_maskz_cvt_roundpd_epi32(U, A, B) \ + ((__m256i)__builtin_ia32_cvtpd2dq512_mask(A, (__v8si)_mm256_setzero_si256(), U, B)) + +#define _mm512_cvt_roundpd_epu32(A, B) \ + ((__m256i)__builtin_ia32_cvtpd2udq512_mask(A, (__v8si)_mm256_undefined_si256(), -1, B)) + +#define _mm512_mask_cvt_roundpd_epu32(W, U, A, B) \ + ((__m256i)__builtin_ia32_cvtpd2udq512_mask(A, (__v8si)(W), U, B)) + +#define _mm512_maskz_cvt_roundpd_epu32(U, A, B) \ + ((__m256i)__builtin_ia32_cvtpd2udq512_mask(A, (__v8si)_mm256_setzero_si256(), U, B)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundps_epi32 (__m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundps_epi32 (__m512i __W, __mmask16 __U, __m512 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundps_epi32 (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundps_epu32 (__m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundps_epu32 (__m512i __W, __mmask16 __U, __m512 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundps_epu32 (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, __R); +} +#else +#define _mm512_cvtt_roundps_epi32(A, B) \ + ((__m512i)__builtin_ia32_cvttps2dq512_mask(A, (__v16si)_mm512_undefined_epi32 (), -1, B)) + +#define _mm512_mask_cvtt_roundps_epi32(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2dq512_mask(A, (__v16si)(W), U, B)) + +#define _mm512_maskz_cvtt_roundps_epi32(U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2dq512_mask(A, (__v16si)_mm512_setzero_si512 (), U, B)) + +#define _mm512_cvtt_roundps_epu32(A, B) \ + ((__m512i)__builtin_ia32_cvttps2udq512_mask(A, (__v16si)_mm512_undefined_epi32 (), -1, B)) + +#define _mm512_mask_cvtt_roundps_epu32(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2udq512_mask(A, (__v16si)(W), U, B)) + +#define _mm512_maskz_cvtt_roundps_epu32(U, A, B) \ + ((__m512i)__builtin_ia32_cvttps2udq512_mask(A, (__v16si)_mm512_setzero_si512 (), U, B)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_epi32 (__m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_epi32 (__m512i __W, __mmask16 __U, __m512 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_epi32 (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_epu32 (__m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_epu32 (__m512i __W, __mmask16 __U, __m512 __A, + const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_epu32 (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, __R); +} +#else +#define _mm512_cvt_roundps_epi32(A, B) \ + ((__m512i)__builtin_ia32_cvtps2dq512_mask(A, (__v16si)_mm512_undefined_epi32 (), -1, B)) + +#define _mm512_mask_cvt_roundps_epi32(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2dq512_mask(A, (__v16si)(W), U, B)) + +#define _mm512_maskz_cvt_roundps_epi32(U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2dq512_mask(A, (__v16si)_mm512_setzero_si512 (), U, B)) + +#define _mm512_cvt_roundps_epu32(A, B) \ + ((__m512i)__builtin_ia32_cvtps2udq512_mask(A, (__v16si)_mm512_undefined_epi32 (), -1, B)) + +#define _mm512_mask_cvt_roundps_epu32(W, U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2udq512_mask(A, (__v16si)(W), U, B)) + +#define _mm512_maskz_cvt_roundps_epu32(U, A, B) \ + ((__m512i)__builtin_ia32_cvtps2udq512_mask(A, (__v16si)_mm512_setzero_si512 (), U, B)) +#endif + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_epi8 (__mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi32_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovsdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi32_epi8 (__mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi32_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovusdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi32_epi8 (__mmask16 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_epi16 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_undefined_si256 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_storeu_epi16 (void * __P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovdw512mem_mask ((__v16hi *) __P, (__v16si) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, + (__v16hi) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_epi16 (__mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi32_epi16 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_undefined_si256 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovsdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, + (__v16hi) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi32_epi16 (__mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi32_epi16 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_undefined_si256 (), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A) +{ + __builtin_ia32_pmovusdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, + (__v16hi) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi32_epi16 (__mmask16 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, + (__v16hi) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_epi32 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi64_epi32 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_storeu_epi32 (void *__P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovsqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, + (__v8si) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi64_epi32 (__mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, + (__v8si) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi64_epi32 (__m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovusqd512mem_mask ((__v8si*) __P, (__v8di) __A, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, + (__v8si) __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi64_epi32 (__mmask8 __M, __m512i __A) +{ + return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, + (__v8si) + _mm256_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_epi16 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, + (__v8hi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_epi16 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, + (__v8hi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi64_epi16 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, + (__v8hi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovsqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi64_epi16 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, + (__v8hi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi64_epi16 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, + (__v8hi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovusqw512mem_mask ((__v8hi*) __P, (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi64_epi16 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, + (__v8hi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovqb512mem_mask ((unsigned long long *) __P, + (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_epi8 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsepi64_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovsqb512mem_mask ((unsigned long long *) __P, (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtsepi64_epi8 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtusepi64_epi8 (__m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, + (__v16qi) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) +{ + __builtin_ia32_pmovusqb512mem_mask ((unsigned long long *) __P, (__v8di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtusepi64_epi8 (__mmask8 __M, __m512i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, + (__v16qi) + _mm_setzero_si128 (), + __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_pd (__m256i __A) +{ + return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A) +{ + return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A) +{ + return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu32_pd (__m256i __A) +{ + return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A) +{ + return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A) +{ + return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi32_ps (__m512i __A, const int __R) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi32_ps (__m512 __W, __mmask16 __U, __m512i __A, + const int __R) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi32_ps (__mmask16 __U, __m512i __A, const int __R) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu32_ps (__m512i __A, const int __R) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu32_ps (__m512 __W, __mmask16 __U, __m512i __A, + const int __R) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu32_ps (__mmask16 __U, __m512i __A, const int __R) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +#else +#define _mm512_cvt_roundepi32_ps(A, B) \ + (__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(A), (__v16sf)_mm512_undefined_ps(), -1, B) + +#define _mm512_mask_cvt_roundepi32_ps(W, U, A, B) \ + (__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(A), W, U, B) + +#define _mm512_maskz_cvt_roundepi32_ps(U, A, B) \ + (__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(A), (__v16sf)_mm512_setzero_ps(), U, B) + +#define _mm512_cvt_roundepu32_ps(A, B) \ + (__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(A), (__v16sf)_mm512_undefined_ps(), -1, B) + +#define _mm512_mask_cvt_roundepu32_ps(W, U, A, B) \ + (__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(A), W, U, B) + +#define _mm512_maskz_cvt_roundepu32_ps(U, A, B) \ + (__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(A), (__v16sf)_mm512_setzero_ps(), U, B) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extractf64x4_pd (__m512d __A, const int __imm) +{ + return (__m256d) __builtin_ia32_extractf64x4_mask ((__v8df) __A, + __imm, + (__v4df) + _mm256_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extractf64x4_pd (__m256d __W, __mmask8 __U, __m512d __A, + const int __imm) +{ + return (__m256d) __builtin_ia32_extractf64x4_mask ((__v8df) __A, + __imm, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extractf64x4_pd (__mmask8 __U, __m512d __A, const int __imm) +{ + return (__m256d) __builtin_ia32_extractf64x4_mask ((__v8df) __A, + __imm, + (__v4df) + _mm256_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extractf32x4_ps (__m512 __A, const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_mask ((__v16sf) __A, + __imm, + (__v4sf) + _mm_undefined_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extractf32x4_ps (__m128 __W, __mmask8 __U, __m512 __A, + const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_mask ((__v16sf) __A, + __imm, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extractf32x4_ps (__mmask8 __U, __m512 __A, const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_mask ((__v16sf) __A, + __imm, + (__v4sf) + _mm_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extracti64x4_epi64 (__m512i __A, const int __imm) +{ + return (__m256i) __builtin_ia32_extracti64x4_mask ((__v8di) __A, + __imm, + (__v4di) + _mm256_undefined_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extracti64x4_epi64 (__m256i __W, __mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_extracti64x4_mask ((__v8di) __A, + __imm, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extracti64x4_epi64 (__mmask8 __U, __m512i __A, const int __imm) +{ + return (__m256i) __builtin_ia32_extracti64x4_mask ((__v8di) __A, + __imm, + (__v4di) + _mm256_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_extracti32x4_epi32 (__m512i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_mask ((__v16si) __A, + __imm, + (__v4si) + _mm_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_extracti32x4_epi32 (__m128i __W, __mmask8 __U, __m512i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_mask ((__v16si) __A, + __imm, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_extracti32x4_epi32 (__mmask8 __U, __m512i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_mask ((__v16si) __A, + __imm, + (__v4si) + _mm_setzero_si128 (), + (__mmask8) __U); +} +#else + +#define _mm512_extractf64x4_pd(X, C) \ + ((__m256d) __builtin_ia32_extractf64x4_mask ((__v8df)(__m512d) (X), \ + (int) (C),\ + (__v4df)(__m256d)_mm256_undefined_pd(),\ + (__mmask8)-1)) + +#define _mm512_mask_extractf64x4_pd(W, U, X, C) \ + ((__m256d) __builtin_ia32_extractf64x4_mask ((__v8df)(__m512d) (X), \ + (int) (C),\ + (__v4df)(__m256d)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_extractf64x4_pd(U, X, C) \ + ((__m256d) __builtin_ia32_extractf64x4_mask ((__v8df)(__m512d) (X), \ + (int) (C),\ + (__v4df)(__m256d)_mm256_setzero_pd(),\ + (__mmask8)(U))) + +#define _mm512_extractf32x4_ps(X, C) \ + ((__m128) __builtin_ia32_extractf32x4_mask ((__v16sf)(__m512) (X), \ + (int) (C),\ + (__v4sf)(__m128)_mm_undefined_ps(),\ + (__mmask8)-1)) + +#define _mm512_mask_extractf32x4_ps(W, U, X, C) \ + ((__m128) __builtin_ia32_extractf32x4_mask ((__v16sf)(__m512) (X), \ + (int) (C),\ + (__v4sf)(__m128)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_extractf32x4_ps(U, X, C) \ + ((__m128) __builtin_ia32_extractf32x4_mask ((__v16sf)(__m512) (X), \ + (int) (C),\ + (__v4sf)(__m128)_mm_setzero_ps(),\ + (__mmask8)(U))) + +#define _mm512_extracti64x4_epi64(X, C) \ + ((__m256i) __builtin_ia32_extracti64x4_mask ((__v8di)(__m512i) (X), \ + (int) (C),\ + (__v4di)(__m256i)_mm256_undefined_si256 (),\ + (__mmask8)-1)) + +#define _mm512_mask_extracti64x4_epi64(W, U, X, C) \ + ((__m256i) __builtin_ia32_extracti64x4_mask ((__v8di)(__m512i) (X), \ + (int) (C),\ + (__v4di)(__m256i)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_extracti64x4_epi64(U, X, C) \ + ((__m256i) __builtin_ia32_extracti64x4_mask ((__v8di)(__m512i) (X), \ + (int) (C),\ + (__v4di)(__m256i)_mm256_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm512_extracti32x4_epi32(X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_mask ((__v16si)(__m512i) (X), \ + (int) (C),\ + (__v4si)(__m128i)_mm_undefined_si128 (),\ + (__mmask8)-1)) + +#define _mm512_mask_extracti32x4_epi32(W, U, X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_mask ((__v16si)(__m512i) (X), \ + (int) (C),\ + (__v4si)(__m128i)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_extracti32x4_epi32(U, X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_mask ((__v16si)(__m512i) (X), \ + (int) (C),\ + (__v4si)(__m128i)_mm_setzero_si128 (),\ + (__mmask8)(U))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_inserti32x4 (__m512i __A, __m128i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x4_mask ((__v16si) __A, + (__v4si) __B, + __imm, + (__v16si) __A, -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_insertf32x4 (__m512 __A, __m128 __B, const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x4_mask ((__v16sf) __A, + (__v4sf) __B, + __imm, + (__v16sf) __A, -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_inserti64x4 (__m512i __A, __m256i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x4_mask ((__v8di) __A, + (__v4di) __B, + __imm, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_inserti64x4 (__m512i __W, __mmask8 __U, __m512i __A, + __m256i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x4_mask ((__v8di) __A, + (__v4di) __B, + __imm, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_inserti64x4 (__mmask8 __U, __m512i __A, __m256i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_inserti64x4_mask ((__v8di) __A, + (__v4di) __B, + __imm, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_insertf64x4 (__m512d __A, __m256d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x4_mask ((__v8df) __A, + (__v4df) __B, + __imm, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_insertf64x4 (__m512d __W, __mmask8 __U, __m512d __A, + __m256d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x4_mask ((__v8df) __A, + (__v4df) __B, + __imm, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_insertf64x4 (__mmask8 __U, __m512d __A, __m256d __B, + const int __imm) +{ + return (__m512d) __builtin_ia32_insertf64x4_mask ((__v8df) __A, + (__v4df) __B, + __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} +#else +#define _mm512_insertf32x4(X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x4_mask ((__v16sf)(__m512) (X), \ + (__v4sf)(__m128) (Y), (int) (C), (__v16sf)(__m512) (X), (__mmask16)(-1))) + +#define _mm512_inserti32x4(X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x4_mask ((__v16si)(__m512i) (X), \ + (__v4si)(__m128i) (Y), (int) (C), (__v16si)(__m512i) (X), (__mmask16)(-1))) + +#define _mm512_insertf64x4(X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x4_mask ((__v8df)(__m512d) (X), \ + (__v4df)(__m256d) (Y), (int) (C), \ + (__v8df)(__m512d)_mm512_undefined_pd(), \ + (__mmask8)-1)) + +#define _mm512_mask_insertf64x4(W, U, X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x4_mask ((__v8df)(__m512d) (X), \ + (__v4df)(__m256d) (Y), (int) (C), \ + (__v8df)(__m512d)(W), \ + (__mmask8)(U))) + +#define _mm512_maskz_insertf64x4(U, X, Y, C) \ + ((__m512d) __builtin_ia32_insertf64x4_mask ((__v8df)(__m512d) (X), \ + (__v4df)(__m256d) (Y), (int) (C), \ + (__v8df)(__m512d)_mm512_setzero_pd(), \ + (__mmask8)(U))) + +#define _mm512_inserti64x4(X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x4_mask ((__v8di)(__m512i) (X), \ + (__v4di)(__m256i) (Y), (int) (C), \ + (__v8di)(__m512i)_mm512_undefined_epi32 (), \ + (__mmask8)-1)) + +#define _mm512_mask_inserti64x4(W, U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x4_mask ((__v8di)(__m512i) (X), \ + (__v4di)(__m256i) (Y), (int) (C),\ + (__v8di)(__m512i)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_inserti64x4(U, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti64x4_mask ((__v8di)(__m512i) (X), \ + (__v4di)(__m256i) (Y), (int) (C), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(U))) +#endif + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_pd (void const *__P) +{ + return *(__m512d_u *)__P; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_pd (__m512d __W, __mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_loadupd512_mask ((const double *) __P, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_pd (__mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_loadupd512_mask ((const double *) __P, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_pd (void *__P, __m512d __A) +{ + *(__m512d_u *)__P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_pd (void *__P, __mmask8 __U, __m512d __A) +{ + __builtin_ia32_storeupd512_mask ((double *) __P, (__v8df) __A, + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_ps (void const *__P) +{ + return *(__m512_u *)__P; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_ps (__m512 __W, __mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_loadups512_mask ((const float *) __P, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_ps (__mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_loadups512_mask ((const float *) __P, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_ps (void *__P, __m512 __A) +{ + *(__m512_u *)__P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_ps (void *__P, __mmask16 __U, __m512 __A) +{ + __builtin_ia32_storeups512_mask ((float *) __P, (__v16sf) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi64 (void const *__P) +{ + return *(__m512i_u *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi64 (void *__P, __m512i __A) +{ + *(__m512i_u *) __P = (__m512i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_epi64 (void *__P, __mmask8 __U, __m512i __A) +{ + __builtin_ia32_storedqudi512_mask ((long long *) __P, (__v8di) __A, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_si512 (void const *__P) +{ + return *(__m512i_u *)__P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi32 (void const *__P) +{ + return *(__m512i_u *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_loadu_epi32 (__mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_si512 (void *__P, __m512i __A) +{ + *(__m512i_u *)__P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi32 (void *__P, __m512i __A) +{ + *(__m512i_u *) __P = (__m512i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_storeu_epi32 (void *__P, __mmask16 __U, __m512i __A) +{ + __builtin_ia32_storedqusi512_mask ((int *) __P, (__v16si) __A, + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutevar_pd (__m512d __A, __m512i __C) +{ + return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A, + (__v8di) __C, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutevar_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512i __C) +{ + return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A, + (__v8di) __C, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutevar_pd (__mmask8 __U, __m512d __A, __m512i __C) +{ + return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A, + (__v8di) __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutevar_ps (__m512 __A, __m512i __C) +{ + return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A, + (__v16si) __C, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutevar_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512i __C) +{ + return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A, + (__v16si) __C, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutevar_ps (__mmask16 __U, __m512 __A, __m512i __C) +{ + return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A, + (__v16si) __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_epi64 (__m512i __A, __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varq512_mask ((__v8di) __I + /* idx */ , + (__v8di) __A, + (__v8di) __B, + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_epi64 (__m512i __A, __mmask8 __U, __m512i __I, + __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varq512_mask ((__v8di) __I + /* idx */ , + (__v8di) __A, + (__v8di) __B, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_epi64 (__m512i __A, __m512i __I, + __mmask8 __U, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermi2varq512_mask ((__v8di) __A, + (__v8di) __I + /* idx */ , + (__v8di) __B, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_epi64 (__mmask8 __U, __m512i __A, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varq512_maskz ((__v8di) __I + /* idx */ , + (__v8di) __A, + (__v8di) __B, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_epi32 (__m512i __A, __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2vard512_mask ((__v16si) __I + /* idx */ , + (__v16si) __A, + (__v16si) __B, + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_epi32 (__m512i __A, __mmask16 __U, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2vard512_mask ((__v16si) __I + /* idx */ , + (__v16si) __A, + (__v16si) __B, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_epi32 (__m512i __A, __m512i __I, + __mmask16 __U, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermi2vard512_mask ((__v16si) __A, + (__v16si) __I + /* idx */ , + (__v16si) __B, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_epi32 (__mmask16 __U, __m512i __A, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2vard512_maskz ((__v16si) __I + /* idx */ , + (__v16si) __A, + (__v16si) __B, + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_pd (__m512d __A, __m512i __I, __m512d __B) +{ + return (__m512d) __builtin_ia32_vpermt2varpd512_mask ((__v8di) __I + /* idx */ , + (__v8df) __A, + (__v8df) __B, + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_pd (__m512d __A, __mmask8 __U, __m512i __I, + __m512d __B) +{ + return (__m512d) __builtin_ia32_vpermt2varpd512_mask ((__v8di) __I + /* idx */ , + (__v8df) __A, + (__v8df) __B, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_pd (__m512d __A, __m512i __I, __mmask8 __U, + __m512d __B) +{ + return (__m512d) __builtin_ia32_vpermi2varpd512_mask ((__v8df) __A, + (__v8di) __I + /* idx */ , + (__v8df) __B, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_pd (__mmask8 __U, __m512d __A, __m512i __I, + __m512d __B) +{ + return (__m512d) __builtin_ia32_vpermt2varpd512_maskz ((__v8di) __I + /* idx */ , + (__v8df) __A, + (__v8df) __B, + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_ps (__m512 __A, __m512i __I, __m512 __B) +{ + return (__m512) __builtin_ia32_vpermt2varps512_mask ((__v16si) __I + /* idx */ , + (__v16sf) __A, + (__v16sf) __B, + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_ps (__m512 __A, __mmask16 __U, __m512i __I, __m512 __B) +{ + return (__m512) __builtin_ia32_vpermt2varps512_mask ((__v16si) __I + /* idx */ , + (__v16sf) __A, + (__v16sf) __B, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_ps (__m512 __A, __m512i __I, __mmask16 __U, + __m512 __B) +{ + return (__m512) __builtin_ia32_vpermi2varps512_mask ((__v16sf) __A, + (__v16si) __I + /* idx */ , + (__v16sf) __B, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I, + __m512 __B) +{ + return (__m512) __builtin_ia32_vpermt2varps512_maskz ((__v16si) __I + /* idx */ , + (__v16sf) __A, + (__v16sf) __B, + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permute_pd (__m512d __X, const int __C) +{ + return (__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df) __X, __C, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permute_pd (__m512d __W, __mmask8 __U, __m512d __X, const int __C) +{ + return (__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df) __X, __C, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permute_pd (__mmask8 __U, __m512d __X, const int __C) +{ + return (__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df) __X, __C, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permute_ps (__m512 __X, const int __C) +{ + return (__m512) __builtin_ia32_vpermilps512_mask ((__v16sf) __X, __C, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permute_ps (__m512 __W, __mmask16 __U, __m512 __X, const int __C) +{ + return (__m512) __builtin_ia32_vpermilps512_mask ((__v16sf) __X, __C, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permute_ps (__mmask16 __U, __m512 __X, const int __C) +{ + return (__m512) __builtin_ia32_vpermilps512_mask ((__v16sf) __X, __C, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} +#else +#define _mm512_permute_pd(X, C) \ + ((__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df)(__m512d)(X), (int)(C), \ + (__v8df)(__m512d)_mm512_undefined_pd(),\ + (__mmask8)(-1))) + +#define _mm512_mask_permute_pd(W, U, X, C) \ + ((__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df)(__m512d)(X), (int)(C), \ + (__v8df)(__m512d)(W), \ + (__mmask8)(U))) + +#define _mm512_maskz_permute_pd(U, X, C) \ + ((__m512d) __builtin_ia32_vpermilpd512_mask ((__v8df)(__m512d)(X), (int)(C), \ + (__v8df)(__m512d)_mm512_setzero_pd(), \ + (__mmask8)(U))) + +#define _mm512_permute_ps(X, C) \ + ((__m512) __builtin_ia32_vpermilps512_mask ((__v16sf)(__m512)(X), (int)(C), \ + (__v16sf)(__m512)_mm512_undefined_ps(),\ + (__mmask16)(-1))) + +#define _mm512_mask_permute_ps(W, U, X, C) \ + ((__m512) __builtin_ia32_vpermilps512_mask ((__v16sf)(__m512)(X), (int)(C), \ + (__v16sf)(__m512)(W), \ + (__mmask16)(U))) + +#define _mm512_maskz_permute_ps(U, X, C) \ + ((__m512) __builtin_ia32_vpermilps512_mask ((__v16sf)(__m512)(X), (int)(C), \ + (__v16sf)(__m512)_mm512_setzero_ps(), \ + (__mmask16)(U))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex_epi64 (__m512i __X, const int __I) +{ + return (__m512i) __builtin_ia32_permdi512_mask ((__v8di) __X, __I, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) (-1)); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex_epi64 (__m512i __W, __mmask8 __M, + __m512i __X, const int __I) +{ + return (__m512i) __builtin_ia32_permdi512_mask ((__v8di) __X, __I, + (__v8di) __W, + (__mmask8) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex_epi64 (__mmask8 __M, __m512i __X, const int __I) +{ + return (__m512i) __builtin_ia32_permdi512_mask ((__v8di) __X, __I, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex_pd (__m512d __X, const int __M) +{ + return (__m512d) __builtin_ia32_permdf512_mask ((__v8df) __X, __M, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex_pd (__m512d __W, __mmask8 __U, __m512d __X, const int __M) +{ + return (__m512d) __builtin_ia32_permdf512_mask ((__v8df) __X, __M, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex_pd (__mmask8 __U, __m512d __X, const int __M) +{ + return (__m512d) __builtin_ia32_permdf512_mask ((__v8df) __X, __M, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} +#else +#define _mm512_permutex_pd(X, M) \ + ((__m512d) __builtin_ia32_permdf512_mask ((__v8df)(__m512d)(X), (int)(M), \ + (__v8df)(__m512d)_mm512_undefined_pd(),\ + (__mmask8)-1)) + +#define _mm512_mask_permutex_pd(W, U, X, M) \ + ((__m512d) __builtin_ia32_permdf512_mask ((__v8df)(__m512d)(X), (int)(M), \ + (__v8df)(__m512d)(W), (__mmask8)(U))) + +#define _mm512_maskz_permutex_pd(U, X, M) \ + ((__m512d) __builtin_ia32_permdf512_mask ((__v8df)(__m512d)(X), (int)(M), \ + (__v8df)(__m512d)_mm512_setzero_pd(),\ + (__mmask8)(U))) + +#define _mm512_permutex_epi64(X, I) \ + ((__m512i) __builtin_ia32_permdi512_mask ((__v8di)(__m512i)(X), \ + (int)(I), \ + (__v8di)(__m512i) \ + (_mm512_undefined_epi32 ()),\ + (__mmask8)(-1))) + +#define _mm512_maskz_permutex_epi64(M, X, I) \ + ((__m512i) __builtin_ia32_permdi512_mask ((__v8di)(__m512i)(X), \ + (int)(I), \ + (__v8di)(__m512i) \ + (_mm512_setzero_si512 ()),\ + (__mmask8)(M))) + +#define _mm512_mask_permutex_epi64(W, M, X, I) \ + ((__m512i) __builtin_ia32_permdi512_mask ((__v8di)(__m512i)(X), \ + (int)(I), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(M))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_epi64 (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y, + (__v8di) __X, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_epi64 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y, + (__v8di) __X, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_epi64 (__m512i __W, __mmask8 __M, __m512i __X, + __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvardi512_mask ((__v8di) __Y, + (__v8di) __X, + (__v8di) __W, + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_epi32 (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y, + (__v16si) __X, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_epi32 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y, + (__v16si) __X, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_epi32 (__m512i __W, __mmask16 __M, __m512i __X, + __m512i __Y) +{ + return (__m512i) __builtin_ia32_permvarsi512_mask ((__v16si) __Y, + (__v16si) __X, + (__v16si) __W, + __M); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_pd (__m512i __X, __m512d __Y) +{ + return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y, + (__v8di) __X, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_pd (__m512d __W, __mmask8 __U, __m512i __X, __m512d __Y) +{ + return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y, + (__v8di) __X, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_pd (__mmask8 __U, __m512i __X, __m512d __Y) +{ + return (__m512d) __builtin_ia32_permvardf512_mask ((__v8df) __Y, + (__v8di) __X, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_ps (__m512i __X, __m512 __Y) +{ + return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y, + (__v16si) __X, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_ps (__m512 __W, __mmask16 __U, __m512i __X, __m512 __Y) +{ + return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y, + (__v16si) __X, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_ps (__mmask16 __U, __m512i __X, __m512 __Y) +{ + return (__m512) __builtin_ia32_permvarsf512_mask ((__v16sf) __Y, + (__v16si) __X, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_ps (__m512 __M, __m512 __V, const int __imm) +{ + return (__m512) __builtin_ia32_shufps512_mask ((__v16sf) __M, + (__v16sf) __V, __imm, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_ps (__m512 __W, __mmask16 __U, __m512 __M, + __m512 __V, const int __imm) +{ + return (__m512) __builtin_ia32_shufps512_mask ((__v16sf) __M, + (__v16sf) __V, __imm, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_ps (__mmask16 __U, __m512 __M, __m512 __V, const int __imm) +{ + return (__m512) __builtin_ia32_shufps512_mask ((__v16sf) __M, + (__v16sf) __V, __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shuffle_pd (__m512d __M, __m512d __V, const int __imm) +{ + return (__m512d) __builtin_ia32_shufpd512_mask ((__v8df) __M, + (__v8df) __V, __imm, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shuffle_pd (__m512d __W, __mmask8 __U, __m512d __M, + __m512d __V, const int __imm) +{ + return (__m512d) __builtin_ia32_shufpd512_mask ((__v8df) __M, + (__v8df) __V, __imm, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shuffle_pd (__mmask8 __U, __m512d __M, __m512d __V, + const int __imm) +{ + return (__m512d) __builtin_ia32_shufpd512_mask ((__v8df) __M, + (__v8df) __V, __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fixupimm_round_pd (__m512d __A, __m512d __B, __m512i __C, + const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fixupimm_round_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512i __C, const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fixupimm_round_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512i __C, const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fixupimm_round_ps (__m512 __A, __m512 __B, __m512i __C, + const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_fixupimmps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fixupimm_round_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512i __C, const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_fixupimmps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fixupimm_round_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512i __C, const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_fixupimmps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) __U, __R); +} + +#else +#define _mm512_shuffle_pd(X, Y, C) \ + ((__m512d)__builtin_ia32_shufpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)_mm512_undefined_pd(),\ + (__mmask8)-1)) + +#define _mm512_mask_shuffle_pd(W, U, X, Y, C) \ + ((__m512d)__builtin_ia32_shufpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)(W),\ + (__mmask8)(U))) + +#define _mm512_maskz_shuffle_pd(U, X, Y, C) \ + ((__m512d)__builtin_ia32_shufpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(C),\ + (__v8df)(__m512d)_mm512_setzero_pd(),\ + (__mmask8)(U))) + +#define _mm512_shuffle_ps(X, Y, C) \ + ((__m512)__builtin_ia32_shufps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)_mm512_undefined_ps(),\ + (__mmask16)-1)) + +#define _mm512_mask_shuffle_ps(W, U, X, Y, C) \ + ((__m512)__builtin_ia32_shufps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)(W),\ + (__mmask16)(U))) + +#define _mm512_maskz_shuffle_ps(U, X, Y, C) \ + ((__m512)__builtin_ia32_shufps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(C),\ + (__v16sf)(__m512)_mm512_setzero_ps(),\ + (__mmask16)(U))) + +#define _mm512_fixupimm_round_pd(X, Y, Z, C, R) \ + ((__m512d)__builtin_ia32_fixupimmpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(-1), (R))) + +#define _mm512_mask_fixupimm_round_pd(X, U, Y, Z, C, R) \ + ((__m512d)__builtin_ia32_fixupimmpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#define _mm512_maskz_fixupimm_round_pd(U, X, Y, Z, C, R) \ + ((__m512d)__builtin_ia32_fixupimmpd512_maskz ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(U), (R))) + +#define _mm512_fixupimm_round_ps(X, Y, Z, C, R) \ + ((__m512)__builtin_ia32_fixupimmps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(-1), (R))) + +#define _mm512_mask_fixupimm_round_ps(X, U, Y, Z, C, R) \ + ((__m512)__builtin_ia32_fixupimmps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(U), (R))) + +#define _mm512_maskz_fixupimm_round_ps(U, X, Y, Z, C, R) \ + ((__m512)__builtin_ia32_fixupimmps512_maskz ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(U), (R))) + +#endif + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movehdup_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_movshdup512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_movehdup_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movshdup512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_movehdup_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movshdup512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_moveldup_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_movsldup512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_moveldup_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movsldup512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_movsldup512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_or_si512 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A | (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_or_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A | (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_or_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pord512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_or_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pord512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_or_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A | (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_or_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_or_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_xor_si512 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A ^ (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_xor_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A ^ (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_xor_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pxord512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_xor_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pxord512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_xor_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A ^ (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_xor_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_xor_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rol_epi32 (__m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prold512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rol_epi32 (__m512i __W, __mmask16 __U, __m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prold512_mask ((__v16si) __A, __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rol_epi32 (__mmask16 __U, __m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prold512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ror_epi32 (__m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prord512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ror_epi32 (__m512i __W, __mmask16 __U, __m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prord512_mask ((__v16si) __A, __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_ror_epi32 (__mmask16 __U, __m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prord512_mask ((__v16si) __A, __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rol_epi64 (__m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prolq512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rol_epi64 (__m512i __W, __mmask8 __U, __m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prolq512_mask ((__v8di) __A, __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rol_epi64 (__mmask8 __U, __m512i __A, const int __B) +{ + return (__m512i) __builtin_ia32_prolq512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ror_epi64 (__m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prorq512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ror_epi64 (__m512i __W, __mmask8 __U, __m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prorq512_mask ((__v8di) __A, __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_ror_epi64 (__mmask8 __U, __m512i __A, int __B) +{ + return (__m512i) __builtin_ia32_prorq512_mask ((__v8di) __A, __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#else +#define _mm512_rol_epi32(A, B) \ + ((__m512i)__builtin_ia32_prold512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)_mm512_undefined_epi32 (), \ + (__mmask16)(-1))) +#define _mm512_mask_rol_epi32(W, U, A, B) \ + ((__m512i)__builtin_ia32_prold512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)(__m512i)(W), \ + (__mmask16)(U))) +#define _mm512_maskz_rol_epi32(U, A, B) \ + ((__m512i)__builtin_ia32_prold512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)_mm512_setzero_si512 (), \ + (__mmask16)(U))) +#define _mm512_ror_epi32(A, B) \ + ((__m512i)__builtin_ia32_prord512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)_mm512_undefined_epi32 (), \ + (__mmask16)(-1))) +#define _mm512_mask_ror_epi32(W, U, A, B) \ + ((__m512i)__builtin_ia32_prord512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)(__m512i)(W), \ + (__mmask16)(U))) +#define _mm512_maskz_ror_epi32(U, A, B) \ + ((__m512i)__builtin_ia32_prord512_mask ((__v16si)(__m512i)(A), \ + (int)(B), \ + (__v16si)_mm512_setzero_si512 (), \ + (__mmask16)(U))) +#define _mm512_rol_epi64(A, B) \ + ((__m512i)__builtin_ia32_prolq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)_mm512_undefined_epi32 (), \ + (__mmask8)(-1))) +#define _mm512_mask_rol_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_prolq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(U))) +#define _mm512_maskz_rol_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_prolq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)_mm512_setzero_si512 (), \ + (__mmask8)(U))) + +#define _mm512_ror_epi64(A, B) \ + ((__m512i)__builtin_ia32_prorq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)_mm512_undefined_epi32 (), \ + (__mmask8)(-1))) +#define _mm512_mask_ror_epi64(W, U, A, B) \ + ((__m512i)__builtin_ia32_prorq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)(__m512i)(W), \ + (__mmask8)(U))) +#define _mm512_maskz_ror_epi64(U, A, B) \ + ((__m512i)__builtin_ia32_prorq512_mask ((__v8di)(__m512i)(A), \ + (int)(B), \ + (__v8di)_mm512_setzero_si512 (), \ + (__mmask8)(U))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_and_si512 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A & (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_and_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v16su) __A & (__v16su) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_and_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_and_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_and_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) ((__v8du) __A & (__v8du) __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_and_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_and_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_pd (), + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_andnot_si512 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_andnot_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_andnot_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_andnot_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_andnot_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_andnot_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_andnot_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_pd (), + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_test_epi32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A, + (__v16si) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A, + (__v16si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_test_epi64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, + (__v8di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, (__v8di) __B, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_testn_epi32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A, + (__v16si) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A, + (__v16si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_testn_epi64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A, + (__v8di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A, + (__v8di) __B, __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_ps (__m512 __A) +{ + return (__m512) _mm512_and_epi32 ((__m512i) __A, + _mm512_set1_epi32 (0x7fffffff)); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) _mm512_mask_and_epi32 ((__m512i) __W, __U, (__m512i) __A, + _mm512_set1_epi32 (0x7fffffff)); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_pd (__m512d __A) +{ + return (__m512d) _mm512_and_epi64 ((__m512i) __A, + _mm512_set1_epi64 (0x7fffffffffffffffLL)); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_abs_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) + _mm512_mask_and_epi64 ((__m512i) __W, __U, (__m512i) __A, + _mm512_set1_epi64 (0x7fffffffffffffffLL)); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhdq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhdq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhdq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckhqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckldq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckldq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_epi32 (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpckldq512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_punpcklqdq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_movedup_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_movddup512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_movedup_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_movddup512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_movedup_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_movddup512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpcklpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpcklpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpcklpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpckhpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpckhpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_unpckhpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpackhi_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpckhps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpackhi_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpckhps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpackhi_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpckhps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_pd (__m256 __A, const int __R) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_pd (__m512d __W, __mmask8 __U, __m256 __A, + const int __R) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_pd (__mmask8 __U, __m256 __A, const int __R) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_ps (__m256i __A, const int __R) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_ps (__m512 __W, __mmask16 __U, __m256i __A, + const int __R) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_ps (__mmask16 __U, __m256i __A, const int __R) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundps_ph (__m512 __A, const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) + _mm256_undefined_si256 (), + -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_ph (__m512 __A, const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) + _mm256_undefined_si256 (), + -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundps_ph (__m256i __U, __mmask16 __W, __m512 __A, + const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) __U, + (__mmask16) __W); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_ph (__m256i __U, __mmask16 __W, __m512 __A, const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) __U, + (__mmask16) __W); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundps_ph (__mmask16 __W, __m512 __A, const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) + _mm256_setzero_si256 (), + (__mmask16) __W); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_ph (__mmask16 __W, __m512 __A, const int __I) +{ + return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A, + __I, + (__v16hi) + _mm256_setzero_si256 (), + (__mmask16) __W); +} +#else +#define _mm512_cvt_roundps_pd(A, B) \ + (__m512d)__builtin_ia32_cvtps2pd512_mask(A, (__v8df)_mm512_undefined_pd(), -1, B) + +#define _mm512_mask_cvt_roundps_pd(W, U, A, B) \ + (__m512d)__builtin_ia32_cvtps2pd512_mask(A, (__v8df)(W), U, B) + +#define _mm512_maskz_cvt_roundps_pd(U, A, B) \ + (__m512d)__builtin_ia32_cvtps2pd512_mask(A, (__v8df)_mm512_setzero_pd(), U, B) + +#define _mm512_cvt_roundph_ps(A, B) \ + (__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(A), (__v16sf)_mm512_undefined_ps(), -1, B) + +#define _mm512_mask_cvt_roundph_ps(W, U, A, B) \ + (__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(A), (__v16sf)(W), U, B) + +#define _mm512_maskz_cvt_roundph_ps(U, A, B) \ + (__m512)__builtin_ia32_vcvtph2ps512_mask((__v16hi)(A), (__v16sf)_mm512_setzero_ps(), U, B) + +#define _mm512_cvt_roundps_ph(A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)_mm256_undefined_si256 (), -1)) +#define _mm512_cvtps_ph(A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)_mm256_undefined_si256 (), -1)) +#define _mm512_mask_cvt_roundps_ph(U, W, A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)(__m256i)(U), (__mmask16) (W))) +#define _mm512_mask_cvtps_ph(U, W, A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)(__m256i)(U), (__mmask16) (W))) +#define _mm512_maskz_cvt_roundps_ph(W, A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)_mm256_setzero_si256 (), (__mmask16) (W))) +#define _mm512_maskz_cvtps_ph(W, A, I) \ + ((__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf)(__m512) (A), (int) (I),\ + (__v16hi)_mm256_setzero_si256 (), (__mmask16) (W))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_ps (__m512d __A, const int __R) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) + _mm256_undefined_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_ps (__m256 __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_ps (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, __R); +} + +#else +#define _mm512_cvt_roundpd_ps(A, B) \ + (__m256)__builtin_ia32_cvtpd2ps512_mask(A, (__v8sf)_mm256_undefined_ps(), -1, B) + +#define _mm512_mask_cvt_roundpd_ps(W, U, A, B) \ + (__m256)__builtin_ia32_cvtpd2ps512_mask(A, (__v8sf)(W), U, B) + +#define _mm512_maskz_cvt_roundpd_ps(U, A, B) \ + (__m256)__builtin_ia32_cvtpd2ps512_mask(A, (__v8sf)_mm256_setzero_ps(), U, B) + +#endif + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_stream_si512 (__m512i * __P, __m512i __A) +{ + __builtin_ia32_movntdq512 ((__v8di *) __P, (__v8di) __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_stream_ps (float *__P, __m512 __A) +{ + __builtin_ia32_movntps512 (__P, (__v16sf) __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_stream_pd (double *__P, __m512d __A) +{ + __builtin_ia32_movntpd512 (__P, (__v8df) __A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_stream_load_si512 (void *__P) +{ + return __builtin_ia32_movntdqa512 ((__v8di *)__P); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_round_ps (__m512 __A, const int __R) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + const int __R) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_round_ps (__mmask16 __U, __m512 __A, const int __R) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_round_pd (__m512d __A, const int __R) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + const int __R) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_round_pd (__mmask8 __U, __m512d __A, const int __R) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_round_pd (__m512d __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + _mm512_undefined_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_round_pd (__m512d __W, __mmask8 __U, __m512d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + (__v8df) __W, __U, + __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_round_pd (__mmask8 __U, __m512d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + (__v8df) + _mm512_setzero_pd (), + __U, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_round_ps (__m512 __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + _mm512_undefined_ps (), + (__mmask16) -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_round_ps (__m512 __W, __mmask16 __U, __m512 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + (__v16sf) __W, __U, + __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_round_ps (__mmask16 __U, __m512 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + (__v16sf) + _mm512_setzero_ps (), + __U, __R); +} + +#else +#define _mm512_getmant_round_pd(X, B, C, R) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)(__m512d)_mm512_undefined_pd(), \ + (__mmask8)-1,\ + (R))) + +#define _mm512_mask_getmant_round_pd(W, U, X, B, C, R) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)(__m512d)(W), \ + (__mmask8)(U),\ + (R))) + +#define _mm512_maskz_getmant_round_pd(U, X, B, C, R) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)(__m512d)_mm512_setzero_pd(), \ + (__mmask8)(U),\ + (R))) +#define _mm512_getmant_round_ps(X, B, C, R) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)(__m512)_mm512_undefined_ps(), \ + (__mmask16)-1,\ + (R))) + +#define _mm512_mask_getmant_round_ps(W, U, X, B, C, R) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)(__m512)(W), \ + (__mmask16)(U),\ + (R))) + +#define _mm512_maskz_getmant_round_ps(U, X, B, C, R) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)(__m512)_mm512_setzero_ps(), \ + (__mmask16)(U),\ + (R))) + +#define _mm512_getexp_round_ps(A, R) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)_mm512_undefined_ps(), (__mmask16)-1, R)) + +#define _mm512_mask_getexp_round_ps(W, U, A, R) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(W), (__mmask16)(U), R)) + +#define _mm512_maskz_getexp_round_ps(U, A, R) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)_mm512_setzero_ps(), (__mmask16)(U), R)) + +#define _mm512_getexp_round_pd(A, R) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)_mm512_undefined_pd(), (__mmask8)-1, R)) + +#define _mm512_mask_getexp_round_pd(W, U, A, R) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(W), (__mmask8)(U), R)) + +#define _mm512_maskz_getexp_round_pd(U, A, R) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)_mm512_setzero_pd(), (__mmask8)(U), R)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_round_ps (__m512 __A, const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, __imm, + (__v16sf) + _mm512_undefined_ps (), + -1, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_round_ps (__m512 __A, __mmask16 __B, __m512 __C, + const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __C, __imm, + (__v16sf) __A, + (__mmask16) __B, __R); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_round_ps (__mmask16 __A, __m512 __B, + const int __imm, const int __R) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __B, + __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __A, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_round_pd (__m512d __A, const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, __imm, + (__v8df) + _mm512_undefined_pd (), + -1, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_round_pd (__m512d __A, __mmask8 __B, + __m512d __C, const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __C, __imm, + (__v8df) __A, + (__mmask8) __B, __R); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_round_pd (__mmask8 __A, __m512d __B, + const int __imm, const int __R) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __B, + __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __A, __R); +} + +#else +#define _mm512_roundscale_round_ps(A, B, R) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(A), (int)(B),\ + (__v16sf)_mm512_undefined_ps(), (__mmask16)(-1), R)) +#define _mm512_mask_roundscale_round_ps(A, B, C, D, R) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(C), \ + (int)(D), \ + (__v16sf)(__m512)(A), \ + (__mmask16)(B), R)) +#define _mm512_maskz_roundscale_round_ps(A, B, C, R) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(B), \ + (int)(C), \ + (__v16sf)_mm512_setzero_ps(),\ + (__mmask16)(A), R)) +#define _mm512_roundscale_round_pd(A, B, R) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(A), (int)(B),\ + (__v8df)_mm512_undefined_pd(), (__mmask8)(-1), R)) +#define _mm512_mask_roundscale_round_pd(A, B, C, D, R) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(C), \ + (int)(D), \ + (__v8df)(__m512d)(A), \ + (__mmask8)(B), R)) +#define _mm512_maskz_roundscale_round_pd(A, B, C, R) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(B), \ + (int)(C), \ + (__v8df)_mm512_setzero_pd(),\ + (__mmask8)(A), R)) +#endif + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_floor_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, + _MM_FROUND_FLOOR, + (__v16sf) __A, -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_floor_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, + _MM_FROUND_FLOOR, + (__v8df) __A, -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ceil_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, + _MM_FROUND_CEIL, + (__v16sf) __A, -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_ceil_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, + _MM_FROUND_CEIL, + (__v8df) __A, -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_floor_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, + _MM_FROUND_FLOOR, + (__v16sf) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_floor_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, + _MM_FROUND_FLOOR, + (__v8df) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ceil_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, + _MM_FROUND_CEIL, + (__v16sf) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_ceil_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, + _MM_FROUND_CEIL, + (__v8df) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_alignr_epi32 (__m512i __A, __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_alignd512_mask ((__v16si) __A, + (__v16si) __B, __imm, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_alignr_epi32 (__m512i __W, __mmask16 __U, __m512i __A, + __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_alignd512_mask ((__v16si) __A, + (__v16si) __B, __imm, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_alignr_epi32 (__mmask16 __U, __m512i __A, __m512i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_alignd512_mask ((__v16si) __A, + (__v16si) __B, __imm, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_alignr_epi64 (__m512i __A, __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_alignq512_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_alignr_epi64 (__m512i __W, __mmask8 __U, __m512i __A, + __m512i __B, const int __imm) +{ + return (__m512i) __builtin_ia32_alignq512_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_alignr_epi64 (__mmask8 __U, __m512i __A, __m512i __B, + const int __imm) +{ + return (__m512i) __builtin_ia32_alignq512_mask ((__v8di) __A, + (__v8di) __B, __imm, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} +#else +#define _mm512_alignr_epi32(X, Y, C) \ + ((__m512i)__builtin_ia32_alignd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C), (__v16si)_mm512_undefined_epi32 (),\ + (__mmask16)-1)) + +#define _mm512_mask_alignr_epi32(W, U, X, Y, C) \ + ((__m512i)__builtin_ia32_alignd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C), (__v16si)(__m512i)(W), \ + (__mmask16)(U))) + +#define _mm512_maskz_alignr_epi32(U, X, Y, C) \ + ((__m512i)__builtin_ia32_alignd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(C), (__v16si)_mm512_setzero_si512 (),\ + (__mmask16)(U))) + +#define _mm512_alignr_epi64(X, Y, C) \ + ((__m512i)__builtin_ia32_alignq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C), (__v8di)_mm512_undefined_epi32 (), \ + (__mmask8)-1)) + +#define _mm512_mask_alignr_epi64(W, U, X, Y, C) \ + ((__m512i)__builtin_ia32_alignq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C), (__v8di)(__m512i)(W), (__mmask8)(U))) + +#define _mm512_maskz_alignr_epi64(U, X, Y, C) \ + ((__m512i)__builtin_ia32_alignq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(C), (__v8di)_mm512_setzero_si512 (),\ + (__mmask8)(U))) +#endif + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epi32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqd512_mask ((__v16si) __A, + (__v16si) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqd512_mask ((__v16si) __A, + (__v16si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq512_mask ((__v8di) __A, + (__v8di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epi64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq512_mask ((__v8di) __A, + (__v8di) __B, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epi32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtd512_mask ((__v16si) __A, + (__v16si) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtd512_mask ((__v16si) __A, + (__v16si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq512_mask ((__v8di) __A, + (__v8di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epi64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq512_mask ((__v8di) __A, + (__v8di) __B, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epi32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epi32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epu32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epu32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epi64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epi64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpge_epu64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpge_epu64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epi32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 2, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epi32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 2, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epu32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 2, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epu32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 2, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epi64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epi64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_epu64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_epu64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epi32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epi32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epu32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epu32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epi64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epi64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_epu64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_epu64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epi32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epi32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epu32_mask (__mmask16 __M, __m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epu32_mask (__m512i __X, __m512i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epi64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epi64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_epu64_mask (__mmask8 __M, __m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_epu64_mask (__m512i __X, __m512i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, 4, + (__mmask8) -1); +} + +#define _MM_CMPINT_EQ 0x0 +#define _MM_CMPINT_LT 0x1 +#define _MM_CMPINT_LE 0x2 +#define _MM_CMPINT_UNUSED 0x3 +#define _MM_CMPINT_NE 0x4 +#define _MM_CMPINT_NLT 0x5 +#define _MM_CMPINT_GE 0x5 +#define _MM_CMPINT_NLE 0x6 +#define _MM_CMPINT_GT 0x6 + +#ifdef __OPTIMIZE__ +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epi64_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epi32_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epu64_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_epu32_mask (__m512i __X, __m512i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_round_pd_mask (__m512d __X, __m512d __Y, const int __P, + const int __R) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, __P, + (__mmask8) -1, __R); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_round_ps_mask (__m512 __X, __m512 __Y, const int __P, const int __R) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, __P, + (__mmask16) -1, __R); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epi64_mask (__mmask8 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq512_mask ((__v8di) __X, + (__v8di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epi32_mask (__mmask16 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_cmpd512_mask ((__v16si) __X, + (__v16si) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epu64_mask (__mmask8 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __X, + (__v8di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_epu32_mask (__mmask16 __U, __m512i __X, __m512i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __X, + (__v16si) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_round_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y, + const int __P, const int __R) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, __P, + (__mmask8) __U, __R); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_round_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y, + const int __P, const int __R) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, __P, + (__mmask16) __U, __R); +} + +#else +#define _mm512_cmp_epi64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm512_cmp_epi32_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(P), \ + (__mmask16)-1)) + +#define _mm512_cmp_epu64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm512_cmp_epu32_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(P), \ + (__mmask16)-1)) + +#define _mm512_cmp_round_pd_mask(X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmppd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(P),\ + (__mmask8)-1, R)) + +#define _mm512_cmp_round_ps_mask(X, Y, P, R) \ + ((__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(P),\ + (__mmask16)-1, R)) + +#define _mm512_mask_cmp_epi64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm512_mask_cmp_epi32_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(P), \ + (__mmask16)(M))) + +#define _mm512_mask_cmp_epu64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di)(__m512i)(X), \ + (__v8di)(__m512i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm512_mask_cmp_epu32_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si)(__m512i)(X), \ + (__v16si)(__m512i)(Y), (int)(P), \ + (__mmask16)(M))) + +#define _mm512_mask_cmp_round_pd_mask(M, X, Y, P, R) \ + ((__mmask8) __builtin_ia32_cmppd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(P),\ + (__mmask8)(M), R)) + +#define _mm512_mask_cmp_round_ps_mask(M, X, Y, P, R) \ + ((__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(P),\ + (__mmask16)(M), R)) + +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32gather_ps (__m512i __index, void const *__addr, int __scale) +{ + __m512 __v1_old = _mm512_undefined_ps (); + __mmask16 __mask = 0xFFFF; + + return (__m512) __builtin_ia32_gathersiv16sf ((__v16sf) __v1_old, + __addr, + (__v16si) __index, + __mask, __scale); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32gather_ps (__m512 __v1_old, __mmask16 __mask, + __m512i __index, void const *__addr, int __scale) +{ + return (__m512) __builtin_ia32_gathersiv16sf ((__v16sf) __v1_old, + __addr, + (__v16si) __index, + __mask, __scale); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32gather_pd (__m256i __index, void const *__addr, int __scale) +{ + __m512d __v1_old = _mm512_undefined_pd (); + __mmask8 __mask = 0xFF; + + return (__m512d) __builtin_ia32_gathersiv8df ((__v8df) __v1_old, + __addr, + (__v8si) __index, __mask, + __scale); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32gather_pd (__m512d __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, int __scale) +{ + return (__m512d) __builtin_ia32_gathersiv8df ((__v8df) __v1_old, + __addr, + (__v8si) __index, + __mask, __scale); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64gather_ps (__m512i __index, void const *__addr, int __scale) +{ + __m256 __v1_old = _mm256_undefined_ps (); + __mmask8 __mask = 0xFF; + + return (__m256) __builtin_ia32_gatherdiv16sf ((__v8sf) __v1_old, + __addr, + (__v8di) __index, __mask, + __scale); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64gather_ps (__m256 __v1_old, __mmask8 __mask, + __m512i __index, void const *__addr, int __scale) +{ + return (__m256) __builtin_ia32_gatherdiv16sf ((__v8sf) __v1_old, + __addr, + (__v8di) __index, + __mask, __scale); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64gather_pd (__m512i __index, void const *__addr, int __scale) +{ + __m512d __v1_old = _mm512_undefined_pd (); + __mmask8 __mask = 0xFF; + + return (__m512d) __builtin_ia32_gatherdiv8df ((__v8df) __v1_old, + __addr, + (__v8di) __index, __mask, + __scale); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64gather_pd (__m512d __v1_old, __mmask8 __mask, + __m512i __index, void const *__addr, int __scale) +{ + return (__m512d) __builtin_ia32_gatherdiv8df ((__v8df) __v1_old, + __addr, + (__v8di) __index, + __mask, __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32gather_epi32 (__m512i __index, void const *__addr, int __scale) +{ + __m512i __v1_old = _mm512_undefined_epi32 (); + __mmask16 __mask = 0xFFFF; + + return (__m512i) __builtin_ia32_gathersiv16si ((__v16si) __v1_old, + __addr, + (__v16si) __index, + __mask, __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32gather_epi32 (__m512i __v1_old, __mmask16 __mask, + __m512i __index, void const *__addr, int __scale) +{ + return (__m512i) __builtin_ia32_gathersiv16si ((__v16si) __v1_old, + __addr, + (__v16si) __index, + __mask, __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32gather_epi64 (__m256i __index, void const *__addr, int __scale) +{ + __m512i __v1_old = _mm512_undefined_epi32 (); + __mmask8 __mask = 0xFF; + + return (__m512i) __builtin_ia32_gathersiv8di ((__v8di) __v1_old, + __addr, + (__v8si) __index, __mask, + __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32gather_epi64 (__m512i __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m512i) __builtin_ia32_gathersiv8di ((__v8di) __v1_old, + __addr, + (__v8si) __index, + __mask, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64gather_epi32 (__m512i __index, void const *__addr, int __scale) +{ + __m256i __v1_old = _mm256_undefined_si256 (); + __mmask8 __mask = 0xFF; + + return (__m256i) __builtin_ia32_gatherdiv16si ((__v8si) __v1_old, + __addr, + (__v8di) __index, + __mask, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64gather_epi32 (__m256i __v1_old, __mmask8 __mask, + __m512i __index, void const *__addr, int __scale) +{ + return (__m256i) __builtin_ia32_gatherdiv16si ((__v8si) __v1_old, + __addr, + (__v8di) __index, + __mask, __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64gather_epi64 (__m512i __index, void const *__addr, int __scale) +{ + __m512i __v1_old = _mm512_undefined_epi32 (); + __mmask8 __mask = 0xFF; + + return (__m512i) __builtin_ia32_gatherdiv8di ((__v8di) __v1_old, + __addr, + (__v8di) __index, __mask, + __scale); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64gather_epi64 (__m512i __v1_old, __mmask8 __mask, + __m512i __index, void const *__addr, + int __scale) +{ + return (__m512i) __builtin_ia32_gatherdiv8di ((__v8di) __v1_old, + __addr, + (__v8di) __index, + __mask, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32scatter_ps (void *__addr, __m512i __index, __m512 __v1, int __scale) +{ + __builtin_ia32_scattersiv16sf (__addr, (__mmask16) 0xFFFF, + (__v16si) __index, (__v16sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32scatter_ps (void *__addr, __mmask16 __mask, + __m512i __index, __m512 __v1, int __scale) +{ + __builtin_ia32_scattersiv16sf (__addr, __mask, (__v16si) __index, + (__v16sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32scatter_pd (void *__addr, __m256i __index, __m512d __v1, + int __scale) +{ + __builtin_ia32_scattersiv8df (__addr, (__mmask8) 0xFF, + (__v8si) __index, (__v8df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32scatter_pd (void *__addr, __mmask8 __mask, + __m256i __index, __m512d __v1, int __scale) +{ + __builtin_ia32_scattersiv8df (__addr, __mask, (__v8si) __index, + (__v8df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64scatter_ps (void *__addr, __m512i __index, __m256 __v1, int __scale) +{ + __builtin_ia32_scatterdiv16sf (__addr, (__mmask8) 0xFF, + (__v8di) __index, (__v8sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64scatter_ps (void *__addr, __mmask8 __mask, + __m512i __index, __m256 __v1, int __scale) +{ + __builtin_ia32_scatterdiv16sf (__addr, __mask, (__v8di) __index, + (__v8sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64scatter_pd (void *__addr, __m512i __index, __m512d __v1, + int __scale) +{ + __builtin_ia32_scatterdiv8df (__addr, (__mmask8) 0xFF, + (__v8di) __index, (__v8df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64scatter_pd (void *__addr, __mmask8 __mask, + __m512i __index, __m512d __v1, int __scale) +{ + __builtin_ia32_scatterdiv8df (__addr, __mask, (__v8di) __index, + (__v8df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32scatter_epi32 (void *__addr, __m512i __index, + __m512i __v1, int __scale) +{ + __builtin_ia32_scattersiv16si (__addr, (__mmask16) 0xFFFF, + (__v16si) __index, (__v16si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32scatter_epi32 (void *__addr, __mmask16 __mask, + __m512i __index, __m512i __v1, int __scale) +{ + __builtin_ia32_scattersiv16si (__addr, __mask, (__v16si) __index, + (__v16si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i32scatter_epi64 (void *__addr, __m256i __index, + __m512i __v1, int __scale) +{ + __builtin_ia32_scattersiv8di (__addr, (__mmask8) 0xFF, + (__v8si) __index, (__v8di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i32scatter_epi64 (void *__addr, __mmask8 __mask, + __m256i __index, __m512i __v1, int __scale) +{ + __builtin_ia32_scattersiv8di (__addr, __mask, (__v8si) __index, + (__v8di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64scatter_epi32 (void *__addr, __m512i __index, + __m256i __v1, int __scale) +{ + __builtin_ia32_scatterdiv16si (__addr, (__mmask8) 0xFF, + (__v8di) __index, (__v8si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64scatter_epi32 (void *__addr, __mmask8 __mask, + __m512i __index, __m256i __v1, int __scale) +{ + __builtin_ia32_scatterdiv16si (__addr, __mask, (__v8di) __index, + (__v8si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_i64scatter_epi64 (void *__addr, __m512i __index, + __m512i __v1, int __scale) +{ + __builtin_ia32_scatterdiv8di (__addr, (__mmask8) 0xFF, + (__v8di) __index, (__v8di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_i64scatter_epi64 (void *__addr, __mmask8 __mask, + __m512i __index, __m512i __v1, int __scale) +{ + __builtin_ia32_scatterdiv8di (__addr, __mask, (__v8di) __index, + (__v8di) __v1, __scale); +} +#else +#define _mm512_i32gather_ps(INDEX, ADDR, SCALE) \ + (__m512) __builtin_ia32_gathersiv16sf ((__v16sf)_mm512_undefined_ps(),\ + (void const *) (ADDR), \ + (__v16si)(__m512i) (INDEX), \ + (__mmask16)0xFFFF, \ + (int) (SCALE)) + +#define _mm512_mask_i32gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512) __builtin_ia32_gathersiv16sf ((__v16sf)(__m512) (V1OLD), \ + (void const *) (ADDR), \ + (__v16si)(__m512i) (INDEX), \ + (__mmask16) (MASK), \ + (int) (SCALE)) + +#define _mm512_i32gather_pd(INDEX, ADDR, SCALE) \ + (__m512d) __builtin_ia32_gathersiv8df ((__v8df)_mm512_undefined_pd(), \ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i32gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512d) __builtin_ia32_gathersiv8df ((__v8df)(__m512d) (V1OLD), \ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i64gather_ps(INDEX, ADDR, SCALE) \ + (__m256) __builtin_ia32_gatherdiv16sf ((__v8sf)_mm256_undefined_ps(), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i64gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256) __builtin_ia32_gatherdiv16sf ((__v8sf)(__m256) (V1OLD), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i64gather_pd(INDEX, ADDR, SCALE) \ + (__m512d) __builtin_ia32_gatherdiv8df ((__v8df)_mm512_undefined_pd(), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i64gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512d) __builtin_ia32_gatherdiv8df ((__v8df)(__m512d) (V1OLD), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i32gather_epi32(INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gathersiv16si ((__v16si)_mm512_undefined_epi32 (),\ + (void const *) (ADDR), \ + (__v16si)(__m512i) (INDEX), \ + (__mmask16)0xFFFF, \ + (int) (SCALE)) + +#define _mm512_mask_i32gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gathersiv16si ((__v16si)(__m512i) (V1OLD), \ + (void const *) (ADDR), \ + (__v16si)(__m512i) (INDEX), \ + (__mmask16) (MASK), \ + (int) (SCALE)) + +#define _mm512_i32gather_epi64(INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gathersiv8di ((__v8di)_mm512_undefined_epi32 (),\ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i32gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gathersiv8di ((__v8di)(__m512i) (V1OLD), \ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i64gather_epi32(INDEX, ADDR, SCALE) \ + (__m256i) __builtin_ia32_gatherdiv16si ((__v8si)_mm256_undefined_si256(),\ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i64gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256i) __builtin_ia32_gatherdiv16si ((__v8si)(__m256i) (V1OLD), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i64gather_epi64(INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gatherdiv8di ((__v8di)_mm512_undefined_epi32 (),\ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8)0xFF, (int) (SCALE)) + +#define _mm512_mask_i64gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m512i) __builtin_ia32_gatherdiv8di ((__v8di)(__m512i) (V1OLD), \ + (void const *) (ADDR), \ + (__v8di)(__m512i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm512_i32scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv16sf ((void *) (ADDR), (__mmask16)0xFFFF, \ + (__v16si)(__m512i) (INDEX), \ + (__v16sf)(__m512) (V1), (int) (SCALE)) + +#define _mm512_mask_i32scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv16sf ((void *) (ADDR), (__mmask16) (MASK), \ + (__v16si)(__m512i) (INDEX), \ + (__v16sf)(__m512) (V1), (int) (SCALE)) + +#define _mm512_i32scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8si)(__m256i) (INDEX), \ + (__v8df)(__m512d) (V1), (int) (SCALE)) + +#define _mm512_mask_i32scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8si)(__m256i) (INDEX), \ + (__v8df)(__m512d) (V1), (int) (SCALE)) + +#define _mm512_i64scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv16sf ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8di)(__m512i) (INDEX), \ + (__v8sf)(__m256) (V1), (int) (SCALE)) + +#define _mm512_mask_i64scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv16sf ((void *) (ADDR), (__mmask16) (MASK), \ + (__v8di)(__m512i) (INDEX), \ + (__v8sf)(__m256) (V1), (int) (SCALE)) + +#define _mm512_i64scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8di)(__m512i) (INDEX), \ + (__v8df)(__m512d) (V1), (int) (SCALE)) + +#define _mm512_mask_i64scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8di)(__m512i) (INDEX), \ + (__v8df)(__m512d) (V1), (int) (SCALE)) + +#define _mm512_i32scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv16si ((void *) (ADDR), (__mmask16)0xFFFF, \ + (__v16si)(__m512i) (INDEX), \ + (__v16si)(__m512i) (V1), (int) (SCALE)) + +#define _mm512_mask_i32scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv16si ((void *) (ADDR), (__mmask16) (MASK), \ + (__v16si)(__m512i) (INDEX), \ + (__v16si)(__m512i) (V1), (int) (SCALE)) + +#define _mm512_i32scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8si)(__m256i) (INDEX), \ + (__v8di)(__m512i) (V1), (int) (SCALE)) + +#define _mm512_mask_i32scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8si)(__m256i) (INDEX), \ + (__v8di)(__m512i) (V1), (int) (SCALE)) + +#define _mm512_i64scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv16si ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8di)(__m512i) (INDEX), \ + (__v8si)(__m256i) (V1), (int) (SCALE)) + +#define _mm512_mask_i64scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv16si ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8di)(__m512i) (INDEX), \ + (__v8si)(__m256i) (V1), (int) (SCALE)) + +#define _mm512_i64scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8di)(__m512i) (INDEX), \ + (__v8di)(__m512i) (V1), (int) (SCALE)) + +#define _mm512_mask_i64scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8di)(__m512i) (INDEX), \ + (__v8di)(__m512i) (V1), (int) (SCALE)) +#endif + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m512d __A) +{ + __builtin_ia32_compressstoredf512_mask ((__v8df *) __P, (__v8df) __A, + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_ps (void *__P, __mmask16 __U, __m512 __A) +{ + __builtin_ia32_compressstoresf512_mask ((__v16sf *) __P, (__v16sf) __A, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m512i __A) +{ + __builtin_ia32_compressstoredi512_mask ((__v8di *) __P, (__v8di) __A, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_epi32 (void *__P, __mmask16 __U, __m512i __A) +{ + __builtin_ia32_compressstoresi512_mask ((__v16si *) __P, (__v16si) __A, + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_expanddf512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_expanddf512_maskz ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_pd (__m512d __W, __mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_expandloaddf512_mask ((const __v8df *) __P, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_pd (__mmask8 __U, void const *__P) +{ + return (__m512d) __builtin_ia32_expandloaddf512_maskz ((const __v8df *) __P, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_expandsf512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_expandsf512_maskz ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_ps (__m512 __W, __mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_expandloadsf512_mask ((const __v16sf *) __P, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_ps (__mmask16 __U, void const *__P) +{ + return (__m512) __builtin_ia32_expandloadsf512_maskz ((const __v16sf *) __P, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_expanddi512_maskz ((__v8di) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_epi64 (__m512i __W, __mmask8 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *) __P, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m512i) + __builtin_ia32_expandloaddi512_maskz ((const __v8di *) __P, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_expandsi512_maskz ((__v16si) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_epi32 (__m512i __W, __mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *) __P, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_epi32 (__mmask16 __U, void const *__P) +{ + return (__m512i) __builtin_ia32_expandloadsi512_maskz ((const __v16si *) __P, + (__v16si) + _mm512_setzero_si512 + (), (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kand (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kandhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kandn (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kandnhi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kor (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kortestz (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kortestzhi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kortestc (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kortestchi ((__mmask16) __A, + (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kxnor (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kxnorhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kxor (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kxorhi ((__mmask16) __A, (__mmask16) __B); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_knot (__mmask16 __A) +{ + return (__mmask16) __builtin_ia32_knothi ((__mmask16) __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kunpackb (__mmask16 __A, __mmask16 __B) +{ + return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_inserti32x4 (__mmask16 __B, __m512i __C, __m128i __D, + const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x4_mask ((__v16si) __C, + (__v4si) __D, + __imm, + (__v16si) + _mm512_setzero_si512 (), + __B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_insertf32x4 (__mmask16 __B, __m512 __C, __m128 __D, + const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x4_mask ((__v16sf) __C, + (__v4sf) __D, + __imm, + (__v16sf) + _mm512_setzero_ps (), __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_inserti32x4 (__m512i __A, __mmask16 __B, __m512i __C, + __m128i __D, const int __imm) +{ + return (__m512i) __builtin_ia32_inserti32x4_mask ((__v16si) __C, + (__v4si) __D, + __imm, + (__v16si) __A, + __B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_insertf32x4 (__m512 __A, __mmask16 __B, __m512 __C, + __m128 __D, const int __imm) +{ + return (__m512) __builtin_ia32_insertf32x4_mask ((__v16sf) __C, + (__v4sf) __D, + __imm, + (__v16sf) __A, __B); +} +#else +#define _mm512_maskz_insertf32x4(A, X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x4_mask ((__v16sf)(__m512) (X), \ + (__v4sf)(__m128) (Y), (int) (C), (__v16sf)_mm512_setzero_ps(), \ + (__mmask16)(A))) + +#define _mm512_maskz_inserti32x4(A, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x4_mask ((__v16si)(__m512i) (X), \ + (__v4si)(__m128i) (Y), (int) (C), (__v16si)_mm512_setzero_si512 (), \ + (__mmask16)(A))) + +#define _mm512_mask_insertf32x4(A, B, X, Y, C) \ + ((__m512) __builtin_ia32_insertf32x4_mask ((__v16sf)(__m512) (X), \ + (__v4sf)(__m128) (Y), (int) (C), (__v16sf)(__m512) (A), \ + (__mmask16)(B))) + +#define _mm512_mask_inserti32x4(A, B, X, Y, C) \ + ((__m512i) __builtin_ia32_inserti32x4_mask ((__v16si)(__m512i) (X), \ + (__v4si)(__m128i) (Y), (int) (C), (__v16si)(__m512i) (A), \ + (__mmask16)(B))) +#endif + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epi64 (__mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epi64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epi64 (__mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epu64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epu64 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_undefined_epi32 (), + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A, + (__v8di) __B, + (__v8di) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epi32 (__mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epi32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epi32 (__mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_epu32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_epu32 (__mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_epu32 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_epu32 (__mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) + _mm512_setzero_si512 (), + __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A, + (__v16si) __B, + (__v16si) __W, __M); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_unpacklo_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpcklps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_unpacklo_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpcklps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_unpacklo_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_unpcklps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_pd (__mmask8 __U, __m512d __A, __m512d __W) +{ + return (__m512d) __builtin_ia32_blendmpd_512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_ps (__mmask16 __U, __m512 __A, __m512 __W) +{ + return (__m512) __builtin_ia32_blendmps_512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_epi64 (__mmask8 __U, __m512i __A, __m512i __W) +{ + return (__m512i) __builtin_ia32_blendmq_512_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_epi32 (__mmask16 __U, __m512i __A, __m512i __W) +{ + return (__m512i) __builtin_ia32_blendmd_512_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_sqrtps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_pd (__m512d __A, __m512d __B) +{ + return (__m512d) ((__v8df)__A + (__v8df)__B); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_ps (__m512 __A, __m512 __B) +{ + return (__m512) ((__v16sf)__A + (__v16sf)__B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_pd (__m512d __A, __m512d __B) +{ + return (__m512d) ((__v8df)__A - (__v8df)__B); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_ps (__m512 __A, __m512 __B) +{ + return (__m512) ((__v16sf)__A - (__v16sf)__B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_pd (__m512d __A, __m512d __B) +{ + return (__m512d) ((__v8df)__A * (__v8df)__B); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_ps (__m512 __A, __m512 __B) +{ + return (__m512) ((__v16sf)__A * (__v16sf)__B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_pd (__m512d __M, __m512d __V) +{ + return (__m512d) ((__v8df)__M / (__v8df)__V); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_pd (__m512d __W, __mmask8 __U, __m512d __M, __m512d __V) +{ + return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __M, + (__v8df) __V, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_pd (__mmask8 __U, __m512d __M, __m512d __V) +{ + return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __M, + (__v8df) __V, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_ps (__m512 __A, __m512 __B) +{ + return (__m512) ((__v16sf)__A / (__v16sf)__B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_pd (__m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_pd (__mmask8 __U, __m512d __A, __m512d __B) +{ + return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_ps (__m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_ps (__mmask16 __U, __m512 __A, __m512 __B) +{ + return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsubadd_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsubadd_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfnmaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_pd (__m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_pd (__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_pd (__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_pd (__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) +{ + return (__m512d) __builtin_ia32_vfnmsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_ps (__m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_ps (__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_ps (__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) +{ + return (__m512) __builtin_ia32_vfnmsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_ps (__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) +{ + return (__m512) __builtin_ia32_vfnmsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttpd_epi32 (__m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttpd_epi32 (__mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttpd_epu32 (__m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttpd_epu32 (__mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_epi32 (__m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_epi32 (__mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_epu32 (__m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_undefined_si256 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_epu32 (__mmask8 __U, __m512d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, + (__v8si) + _mm256_setzero_si256 (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttps_epi32 (__m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttps_epi32 (__mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttps_epu32 (__m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_epi32 (__m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_epi32 (__mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_epu32 (__m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_undefined_epi32 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_epu32 (__mmask16 __U, __m512 __A) +{ + return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsd_f64 (__m512d __A) +{ + return __A[0]; +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtss_f32 (__m512 __A) +{ + return __A[0]; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_ps (__m512i __A) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_ps (__m512 __W, __mmask16 __U, __m512i __A) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A) +{ + return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu32_ps (__m512i __A) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu32_ps (__m512 __W, __mmask16 __U, __m512i __A) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A) +{ + return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fixupimm_pd (__m512d __A, __m512d __B, __m512i __C, const int __imm) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fixupimm_pd (__m512d __A, __mmask8 __U, __m512d __B, + __m512i __C, const int __imm) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fixupimm_pd (__mmask8 __U, __m512d __A, __m512d __B, + __m512i __C, const int __imm) +{ + return (__m512d) __builtin_ia32_fixupimmpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8di) __C, + __imm, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fixupimm_ps (__m512 __A, __m512 __B, __m512i __C, const int __imm) +{ + return (__m512) __builtin_ia32_fixupimmps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fixupimm_ps (__m512 __A, __mmask16 __U, __m512 __B, + __m512i __C, const int __imm) +{ + return (__m512) __builtin_ia32_fixupimmps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fixupimm_ps (__mmask16 __U, __m512 __A, __m512 __B, + __m512i __C, const int __imm) +{ + return (__m512) __builtin_ia32_fixupimmps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16si) __C, + __imm, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm512_fixupimm_pd(X, Y, Z, C) \ + ((__m512d)__builtin_ia32_fixupimmpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(-1), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_fixupimm_pd(X, U, Y, Z, C) \ + ((__m512d)__builtin_ia32_fixupimmpd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_fixupimm_pd(U, X, Y, Z, C) \ + ((__m512d)__builtin_ia32_fixupimmpd512_maskz ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (__v8di)(__m512i)(Z), (int)(C), \ + (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_fixupimm_ps(X, Y, Z, C) \ + ((__m512)__builtin_ia32_fixupimmps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(-1), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_fixupimm_ps(X, U, Y, Z, C) \ + ((__m512)__builtin_ia32_fixupimmps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_fixupimm_ps(U, X, Y, Z, C) \ + ((__m512)__builtin_ia32_fixupimmps512_maskz ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (__v16si)(__m512i)(Z), (int)(C), \ + (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#endif + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsi512_si32 (__m512i __A) +{ + __v16si __B = (__v16si) __A; + return __B[0]; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtps_pd (__m256 __A) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtps_pd (__m512d __W, __mmask8 __U, __m256 __A) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A) +{ + return (__m512d) __builtin_ia32_cvtps2pd512_mask ((__v8sf) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_ps (__m256i __A) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_ps (__m512 __W, __mmask16 __U, __m256i __A) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_ps (__mmask16 __U, __m256i __A) +{ + return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_ps (__m512d __A) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) + _mm256_undefined_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A) +{ + return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, + (__v8sf) + _mm256_setzero_ps (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_ps (__m512 __A) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_ps (__m512 __W, __mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) __W, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) +{ + return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_pd (__m512d __A) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_pd (__m512d __W, __mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) __W, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_pd (__mmask8 __U, __m512d __A) +{ + return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_pd (__m512d __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + _mm512_undefined_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_pd (__m512d __W, __mmask8 __U, __m512d __A, + _MM_MANTISSA_NORM_ENUM __B, _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + (__v8df) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_pd (__mmask8 __U, __m512d __A, + _MM_MANTISSA_NORM_ENUM __B, _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512d) __builtin_ia32_getmantpd512_mask ((__v8df) __A, + (__C << 2) | __B, + (__v8df) + _mm512_setzero_pd (), + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_ps (__m512 __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + _mm512_undefined_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_ps (__m512 __W, __mmask16 __U, __m512 __A, + _MM_MANTISSA_NORM_ENUM __B, _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + (__v16sf) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_ps (__mmask16 __U, __m512 __A, + _MM_MANTISSA_NORM_ENUM __B, _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512) __builtin_ia32_getmantps512_mask ((__v16sf) __A, + (__C << 2) | __B, + (__v16sf) + _mm512_setzero_ps (), + __U, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm512_getmant_pd(X, B, C) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)_mm512_undefined_pd(), \ + (__mmask8)-1,\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_getmant_pd(W, U, X, B, C) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)(__m512d)(W), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_getmant_pd(U, X, B, C) \ + ((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \ + (int)(((C)<<2) | (B)), \ + (__v8df)_mm512_setzero_pd(), \ + (__mmask8)(U),\ + _MM_FROUND_CUR_DIRECTION)) +#define _mm512_getmant_ps(X, B, C) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)_mm512_undefined_ps(), \ + (__mmask16)-1,\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_getmant_ps(W, U, X, B, C) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)(__m512)(W), \ + (__mmask16)(U),\ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_getmant_ps(U, X, B, C) \ + ((__m512)__builtin_ia32_getmantps512_mask ((__v16sf)(__m512)(X), \ + (int)(((C)<<2) | (B)), \ + (__v16sf)_mm512_setzero_ps(), \ + (__mmask16)(U),\ + _MM_FROUND_CUR_DIRECTION)) +#define _mm512_getexp_ps(A) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)_mm512_undefined_ps(), (__mmask16)-1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_getexp_ps(W, U, A) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(W), (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_getexp_ps(U, A) \ + ((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)_mm512_setzero_ps(), (__mmask16)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_getexp_pd(A) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)_mm512_undefined_pd(), (__mmask8)-1, _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_getexp_pd(W, U, A) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(W), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_getexp_pd(U, A) \ + ((__m512d)__builtin_ia32_getexppd512_mask((__v8df)(__m512d)(A), \ + (__v8df)_mm512_setzero_pd(), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_ps (__m512 __A, const int __imm) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, __imm, + (__v16sf) + _mm512_undefined_ps (), + -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_ps (__m512 __A, __mmask16 __B, __m512 __C, + const int __imm) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __C, __imm, + (__v16sf) __A, + (__mmask16) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_ps (__mmask16 __A, __m512 __B, const int __imm) +{ + return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __B, + __imm, + (__v16sf) + _mm512_setzero_ps (), + (__mmask16) __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_pd (__m512d __A, const int __imm) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, __imm, + (__v8df) + _mm512_undefined_pd (), + -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_pd (__m512d __A, __mmask8 __B, __m512d __C, + const int __imm) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __C, __imm, + (__v8df) __A, + (__mmask8) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_pd (__mmask8 __A, __m512d __B, const int __imm) +{ + return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __B, + __imm, + (__v8df) + _mm512_setzero_pd (), + (__mmask8) __A, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm512_roundscale_ps(A, B) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(A), (int)(B),\ + (__v16sf)_mm512_undefined_ps(), (__mmask16)(-1), _MM_FROUND_CUR_DIRECTION)) +#define _mm512_mask_roundscale_ps(A, B, C, D) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(C), \ + (int)(D), \ + (__v16sf)(__m512)(A), \ + (__mmask16)(B), _MM_FROUND_CUR_DIRECTION)) +#define _mm512_maskz_roundscale_ps(A, B, C) \ + ((__m512) __builtin_ia32_rndscaleps_mask ((__v16sf)(__m512)(B), \ + (int)(C), \ + (__v16sf)_mm512_setzero_ps(),\ + (__mmask16)(A), _MM_FROUND_CUR_DIRECTION)) +#define _mm512_roundscale_pd(A, B) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(A), (int)(B),\ + (__v8df)_mm512_undefined_pd(), (__mmask8)(-1), _MM_FROUND_CUR_DIRECTION)) +#define _mm512_mask_roundscale_pd(A, B, C, D) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(C), \ + (int)(D), \ + (__v8df)(__m512d)(A), \ + (__mmask8)(B), _MM_FROUND_CUR_DIRECTION)) +#define _mm512_maskz_roundscale_pd(A, B, C) \ + ((__m512d) __builtin_ia32_rndscalepd_mask ((__v8df)(__m512d)(B), \ + (int)(C), \ + (__v8df)_mm512_setzero_pd(),\ + (__mmask8)(A), _MM_FROUND_CUR_DIRECTION)) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_pd_mask (__m512d __X, __m512d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, __P, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_ps_mask (__m512 __X, __m512 __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, __P, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, __P, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, __P, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#else +#define _mm512_cmp_pd_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(P),\ + (__mmask8)-1,_MM_FROUND_CUR_DIRECTION)) + +#define _mm512_cmp_ps_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(P),\ + (__mmask16)-1,_MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_cmp_pd_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd512_mask ((__v8df)(__m512d)(X), \ + (__v8df)(__m512d)(Y), (int)(P),\ + (__mmask8)(M), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_cmp_ps_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf)(__m512)(X), \ + (__v16sf)(__m512)(Y), (int)(P),\ + (__mmask16)(M),_MM_FROUND_CUR_DIRECTION)) + +#endif + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_EQ_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_EQ_OQ, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_LT_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_LT_OS, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_LE_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_LE_OS, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpunord_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_UNORD_Q, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpunord_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_UNORD_Q, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NEQ_UQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NEQ_UQ, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpnlt_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NLT_US, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpnlt_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NLT_US, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpnle_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NLE_US, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpnle_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_NLE_US, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpord_pd_mask (__m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_ORD_Q, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpord_pd_mask (__mmask8 __U, __m512d __X, __m512d __Y) +{ + return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X, + (__v8df) __Y, _CMP_ORD_Q, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_EQ_OQ, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_EQ_OQ, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmplt_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_LT_OS, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmplt_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_LT_OS, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmple_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_LE_OS, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmple_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_LE_OS, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpunord_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_UNORD_Q, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpunord_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_UNORD_Q, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpneq_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NEQ_UQ, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpneq_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NEQ_UQ, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpnlt_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NLT_US, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpnlt_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NLT_US, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpnle_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NLE_US, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpnle_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_NLE_US, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpord_ps_mask (__m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_ORD_Q, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpord_ps_mask (__mmask16 __U, __m512 __X, __m512 __Y) +{ + return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) __X, + (__v16sf) __Y, _CMP_ORD_Q, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_kmov (__mmask16 __A) +{ + return __builtin_ia32_kmovw (__A); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd_ps (__m512d __A) +{ + return (__m512) (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd_si512 (__m512d __A) +{ + return (__m512i) (__A); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps_pd (__m512 __A) +{ + return (__m512d) (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps_si512 (__m512 __A) +{ + return (__m512i) (__A); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi512_ps (__m512i __A) +{ + return (__m512) (__A); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi512_pd (__m512i __A) +{ + return (__m512d) (__A); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd512_pd128 (__m512d __A) +{ + return (__m128d)_mm512_extractf32x4_ps((__m512)__A, 0); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps512_ps128 (__m512 __A) +{ + return _mm512_extractf32x4_ps(__A, 0); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi512_si128 (__m512i __A) +{ + return (__m128i)_mm512_extracti32x4_epi32((__m512i)__A, 0); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd512_pd256 (__m512d __A) +{ + return _mm512_extractf64x4_pd(__A, 0); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps512_ps256 (__m512 __A) +{ + return (__m256)_mm512_extractf64x4_pd((__m512d)__A, 0); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi512_si256 (__m512i __A) +{ + return (__m256i)_mm512_extractf64x4_pd((__m512d)__A, 0); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd128_pd512 (__m128d __A) +{ + return (__m512d) __builtin_ia32_pd512_pd((__m128d)__A); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps128_ps512 (__m128 __A) +{ + return (__m512) __builtin_ia32_ps512_ps((__m128)__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi128_si512 (__m128i __A) +{ + return (__m512i) __builtin_ia32_si512_si((__v4si)__A); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd256_pd512 (__m256d __A) +{ + return __builtin_ia32_pd512_256pd (__A); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps256_ps512 (__m256 __A) +{ + return __builtin_ia32_ps512_256ps (__A); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi256_si512 (__m256i __A) +{ + return (__m512i)__builtin_ia32_si512_256si ((__v8si)__A); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextpd128_pd512 (__m128d __A) +{ + return (__m512d) _mm512_insertf32x4 (_mm512_setzero_ps (), (__m128) __A, 0); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextps128_ps512 (__m128 __A) +{ + return _mm512_insertf32x4 (_mm512_setzero_ps (), __A, 0); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextsi128_si512 (__m128i __A) +{ + return _mm512_inserti32x4 (_mm512_setzero_si512 (), __A, 0); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextpd256_pd512 (__m256d __A) +{ + return _mm512_insertf64x4 (_mm512_setzero_pd (), __A, 0); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextps256_ps512 (__m256 __A) +{ + return (__m512) _mm512_insertf64x4 (_mm512_setzero_pd (), (__m256d) __A, 0); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextsi256_si512 (__m256i __A) +{ + return _mm512_inserti64x4 (_mm512_setzero_si512 (), __A, 0); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epu32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __A, + (__v16si) __B, 0, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epu32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __A, + (__v16si) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpeq_epu64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __A, + (__v8di) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpeq_epu64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __A, + (__v8di) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epu32_mask (__m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __A, + (__v16si) __B, 6, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epu32_mask (__mmask16 __U, __m512i __A, __m512i __B) +{ + return (__mmask16) __builtin_ia32_ucmpd512_mask ((__v16si) __A, + (__v16si) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmpgt_epu64_mask (__mmask8 __U, __m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __A, + (__v8di) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmpgt_epu64_mask (__m512i __A, __m512i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq512_mask ((__v8di) __A, + (__v8di) __B, 6, + (__mmask8) -1); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __v8si __T1 = (__v8si) _mm512_extracti64x4_epi64 (__A, 1); \ + __v8si __T2 = (__v8si) _mm512_extracti64x4_epi64 (__A, 0); \ + __m256i __T3 = (__m256i) (__T1 op __T2); \ + __v4si __T4 = (__v4si) _mm256_extracti128_si256 (__T3, 1); \ + __v4si __T5 = (__v4si) _mm256_extracti128_si256 (__T3, 0); \ + __v4si __T6 = __T4 op __T5; \ + __v4si __T7 = __builtin_shuffle (__T6, (__v4si) { 2, 3, 0, 1 }); \ + __v4si __T8 = __T6 op __T7; \ + return __T8[0] op __T8[1] + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_add_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (+); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_mul_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (*); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_and_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (&); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_or_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (|); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_add_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi32 (__U, __A); + __MM512_REDUCE_OP (+); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_mul_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi32 (_mm512_set1_epi32 (1), __U, __A); + __MM512_REDUCE_OP (*); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_and_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi32 (_mm512_set1_epi32 (~0), __U, __A); + __MM512_REDUCE_OP (&); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_or_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi32 (__U, __A); + __MM512_REDUCE_OP (|); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m256i __T1 = (__m256i) _mm512_extracti64x4_epi64 (__A, 1); \ + __m256i __T2 = (__m256i) _mm512_extracti64x4_epi64 (__A, 0); \ + __m256i __T3 = _mm256_##op (__T1, __T2); \ + __m128i __T4 = (__m128i) _mm256_extracti128_si256 (__T3, 1); \ + __m128i __T5 = (__m128i) _mm256_extracti128_si256 (__T3, 0); \ + __m128i __T6 = _mm_##op (__T4, __T5); \ + __m128i __T7 = (__m128i) __builtin_shuffle ((__v4si) __T6, \ + (__v4si) { 2, 3, 0, 1 }); \ + __m128i __T8 = _mm_##op (__T6, __T7); \ + __m128i __T9 = (__m128i) __builtin_shuffle ((__v4si) __T8, \ + (__v4si) { 1, 0, 1, 0 }); \ + __v4si __T10 = (__v4si) _mm_##op (__T8, __T9); \ + return __T10[0] + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (min_epi32); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_epi32 (__m512i __A) +{ + __MM512_REDUCE_OP (max_epi32); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_epu32 (__m512i __A) +{ + __MM512_REDUCE_OP (min_epu32); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_epu32 (__m512i __A) +{ + __MM512_REDUCE_OP (max_epu32); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi32 (_mm512_set1_epi32 (__INT_MAX__), __U, __A); + __MM512_REDUCE_OP (min_epi32); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_epi32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi32 (_mm512_set1_epi32 (-__INT_MAX__ - 1), __U, __A); + __MM512_REDUCE_OP (max_epi32); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_epu32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi32 (_mm512_set1_epi32 (~0), __U, __A); + __MM512_REDUCE_OP (min_epu32); +} + +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_epu32 (__mmask16 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi32 (__U, __A); + __MM512_REDUCE_OP (max_epu32); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m256 __T1 = (__m256) _mm512_extractf64x4_pd ((__m512d) __A, 1); \ + __m256 __T2 = (__m256) _mm512_extractf64x4_pd ((__m512d) __A, 0); \ + __m256 __T3 = __T1 op __T2; \ + __m128 __T4 = _mm256_extractf128_ps (__T3, 1); \ + __m128 __T5 = _mm256_extractf128_ps (__T3, 0); \ + __m128 __T6 = __T4 op __T5; \ + __m128 __T7 = __builtin_shuffle (__T6, (__v4si) { 2, 3, 0, 1 }); \ + __m128 __T8 = __T6 op __T7; \ + return __T8[0] op __T8[1] + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_add_ps (__m512 __A) +{ + __MM512_REDUCE_OP (+); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_mul_ps (__m512 __A) +{ + __MM512_REDUCE_OP (*); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_add_ps (__mmask16 __U, __m512 __A) +{ + __A = _mm512_maskz_mov_ps (__U, __A); + __MM512_REDUCE_OP (+); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_mul_ps (__mmask16 __U, __m512 __A) +{ + __A = _mm512_mask_mov_ps (_mm512_set1_ps (1.0f), __U, __A); + __MM512_REDUCE_OP (*); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m256 __T1 = (__m256) _mm512_extractf64x4_pd ((__m512d) __A, 1); \ + __m256 __T2 = (__m256) _mm512_extractf64x4_pd ((__m512d) __A, 0); \ + __m256 __T3 = _mm256_##op (__T1, __T2); \ + __m128 __T4 = _mm256_extractf128_ps (__T3, 1); \ + __m128 __T5 = _mm256_extractf128_ps (__T3, 0); \ + __m128 __T6 = _mm_##op (__T4, __T5); \ + __m128 __T7 = __builtin_shuffle (__T6, (__v4si) { 2, 3, 0, 1 }); \ + __m128 __T8 = _mm_##op (__T6, __T7); \ + __m128 __T9 = __builtin_shuffle (__T8, (__v4si) { 1, 0, 1, 0 }); \ + __m128 __T10 = _mm_##op (__T8, __T9); \ + return __T10[0] + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_ps (__m512 __A) +{ + __MM512_REDUCE_OP (min_ps); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_ps (__m512 __A) +{ + __MM512_REDUCE_OP (max_ps); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_ps (__mmask16 __U, __m512 __A) +{ + __A = _mm512_mask_mov_ps (_mm512_set1_ps (__builtin_inff ()), __U, __A); + __MM512_REDUCE_OP (min_ps); +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_ps (__mmask16 __U, __m512 __A) +{ + __A = _mm512_mask_mov_ps (_mm512_set1_ps (-__builtin_inff ()), __U, __A); + __MM512_REDUCE_OP (max_ps); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __v4di __T1 = (__v4di) _mm512_extracti64x4_epi64 (__A, 1); \ + __v4di __T2 = (__v4di) _mm512_extracti64x4_epi64 (__A, 0); \ + __m256i __T3 = (__m256i) (__T1 op __T2); \ + __v2di __T4 = (__v2di) _mm256_extracti128_si256 (__T3, 1); \ + __v2di __T5 = (__v2di) _mm256_extracti128_si256 (__T3, 0); \ + __v2di __T6 = __T4 op __T5; \ + return __T6[0] op __T6[1] + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_add_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (+); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_mul_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (*); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_and_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (&); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_or_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (|); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_add_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi64 (__U, __A); + __MM512_REDUCE_OP (+); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_mul_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi64 (_mm512_set1_epi64 (1LL), __U, __A); + __MM512_REDUCE_OP (*); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_and_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi64 (_mm512_set1_epi64 (~0LL), __U, __A); + __MM512_REDUCE_OP (&); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_or_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi64 (__U, __A); + __MM512_REDUCE_OP (|); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m512i __T1 = _mm512_shuffle_i64x2 (__A, __A, 0x4e); \ + __m512i __T2 = _mm512_##op (__A, __T1); \ + __m512i __T3 \ + = (__m512i) __builtin_shuffle ((__v8di) __T2, \ + (__v8di) { 2, 3, 0, 1, 6, 7, 4, 5 });\ + __m512i __T4 = _mm512_##op (__T2, __T3); \ + __m512i __T5 \ + = (__m512i) __builtin_shuffle ((__v8di) __T4, \ + (__v8di) { 1, 0, 3, 2, 5, 4, 7, 6 });\ + __v8di __T6 = (__v8di) _mm512_##op (__T4, __T5); \ + return __T6[0] + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (min_epi64); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_epi64 (__m512i __A) +{ + __MM512_REDUCE_OP (max_epi64); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi64 (_mm512_set1_epi64 (__LONG_LONG_MAX__), + __U, __A); + __MM512_REDUCE_OP (min_epi64); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_epi64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi64 (_mm512_set1_epi64 (-__LONG_LONG_MAX__ - 1), + __U, __A); + __MM512_REDUCE_OP (max_epi64); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_epu64 (__m512i __A) +{ + __MM512_REDUCE_OP (min_epu64); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_epu64 (__m512i __A) +{ + __MM512_REDUCE_OP (max_epu64); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_epu64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_mask_mov_epi64 (_mm512_set1_epi64 (~0LL), __U, __A); + __MM512_REDUCE_OP (min_epu64); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_epu64 (__mmask8 __U, __m512i __A) +{ + __A = _mm512_maskz_mov_epi64 (__U, __A); + __MM512_REDUCE_OP (max_epu64); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m256d __T1 = (__m256d) _mm512_extractf64x4_pd (__A, 1); \ + __m256d __T2 = (__m256d) _mm512_extractf64x4_pd (__A, 0); \ + __m256d __T3 = __T1 op __T2; \ + __m128d __T4 = _mm256_extractf128_pd (__T3, 1); \ + __m128d __T5 = _mm256_extractf128_pd (__T3, 0); \ + __m128d __T6 = __T4 op __T5; \ + return __T6[0] op __T6[1] + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_add_pd (__m512d __A) +{ + __MM512_REDUCE_OP (+); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_mul_pd (__m512d __A) +{ + __MM512_REDUCE_OP (*); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_add_pd (__mmask8 __U, __m512d __A) +{ + __A = _mm512_maskz_mov_pd (__U, __A); + __MM512_REDUCE_OP (+); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_mul_pd (__mmask8 __U, __m512d __A) +{ + __A = _mm512_mask_mov_pd (_mm512_set1_pd (1.0), __U, __A); + __MM512_REDUCE_OP (*); +} + +#undef __MM512_REDUCE_OP +#define __MM512_REDUCE_OP(op) \ + __m256d __T1 = (__m256d) _mm512_extractf64x4_pd (__A, 1); \ + __m256d __T2 = (__m256d) _mm512_extractf64x4_pd (__A, 0); \ + __m256d __T3 = _mm256_##op (__T1, __T2); \ + __m128d __T4 = _mm256_extractf128_pd (__T3, 1); \ + __m128d __T5 = _mm256_extractf128_pd (__T3, 0); \ + __m128d __T6 = _mm_##op (__T4, __T5); \ + __m128d __T7 = (__m128d) __builtin_shuffle (__T6, (__v2di) { 1, 0 }); \ + __m128d __T8 = _mm_##op (__T6, __T7); \ + return __T8[0] + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_pd (__m512d __A) +{ + __MM512_REDUCE_OP (min_pd); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_pd (__m512d __A) +{ + __MM512_REDUCE_OP (max_pd); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_min_pd (__mmask8 __U, __m512d __A) +{ + __A = _mm512_mask_mov_pd (_mm512_set1_pd (__builtin_inf ()), __U, __A); + __MM512_REDUCE_OP (min_pd); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_max_pd (__mmask8 __U, __m512d __A) +{ + __A = _mm512_mask_mov_pd (_mm512_set1_pd (-__builtin_inf ()), __U, __A); + __MM512_REDUCE_OP (max_pd); +} + +#undef __MM512_REDUCE_OP + +#ifdef __DISABLE_AVX512F_512__ +#undef __DISABLE_AVX512F_512__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512F_512__ */ + +#endif /* _AVX512FINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512fp16intrin.h b/template/sysroot/include/avx512fp16intrin.h new file mode 100644 index 0000000..f86050b --- /dev/null +++ b/template/sysroot/include/avx512fp16intrin.h @@ -0,0 +1,7246 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512FP16INTRIN_H_INCLUDED +#define _AVX512FP16INTRIN_H_INCLUDED + +#if !defined (__AVX512FP16__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512fp16,no-evex512") +#define __DISABLE_AVX512FP16__ +#endif /* __AVX512FP16__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef _Float16 __v8hf __attribute__ ((__vector_size__ (16))); +typedef _Float16 __v16hf __attribute__ ((__vector_size__ (32))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef _Float16 __m256h __attribute__ ((__vector_size__ (32), __may_alias__)); + +/* Unaligned version of the same type. */ +typedef _Float16 __m128h_u __attribute__ ((__vector_size__ (16), \ + __may_alias__, __aligned__ (1))); +typedef _Float16 __m256h_u __attribute__ ((__vector_size__ (32), \ + __may_alias__, __aligned__ (1))); + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_ph (_Float16 __A7, _Float16 __A6, _Float16 __A5, + _Float16 __A4, _Float16 __A3, _Float16 __A2, + _Float16 __A1, _Float16 __A0) +{ + return __extension__ (__m128h)(__v8hf){ __A0, __A1, __A2, __A3, + __A4, __A5, __A6, __A7 }; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_ph (_Float16 __A15, _Float16 __A14, _Float16 __A13, + _Float16 __A12, _Float16 __A11, _Float16 __A10, + _Float16 __A9, _Float16 __A8, _Float16 __A7, + _Float16 __A6, _Float16 __A5, _Float16 __A4, + _Float16 __A3, _Float16 __A2, _Float16 __A1, + _Float16 __A0) +{ + return __extension__ (__m256h)(__v16hf){ __A0, __A1, __A2, __A3, + __A4, __A5, __A6, __A7, + __A8, __A9, __A10, __A11, + __A12, __A13, __A14, __A15 }; +} + +/* Create vectors of elements in the reversed order from _mm_set_ph + and _mm256_set_ph functions. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2, + _Float16 __A3, _Float16 __A4, _Float16 __A5, + _Float16 __A6, _Float16 __A7) +{ + return _mm_set_ph (__A7, __A6, __A5, __A4, __A3, __A2, __A1, __A0); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2, + _Float16 __A3, _Float16 __A4, _Float16 __A5, + _Float16 __A6, _Float16 __A7, _Float16 __A8, + _Float16 __A9, _Float16 __A10, _Float16 __A11, + _Float16 __A12, _Float16 __A13, _Float16 __A14, + _Float16 __A15) +{ + return _mm256_set_ph (__A15, __A14, __A13, __A12, __A11, __A10, __A9, + __A8, __A7, __A6, __A5, __A4, __A3, __A2, __A1, + __A0); +} + +/* Broadcast _Float16 to vector. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_ph (_Float16 __A) +{ + return _mm_set_ph (__A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_ph (_Float16 __A) +{ + return _mm256_set_ph (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +/* Create a vector with all zeros. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_ph (void) +{ + return _mm_set1_ph (0.0f16); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setzero_ph (void) +{ + return _mm256_set1_ph (0.0f16); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_undefined_ph (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128h __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_undefined_ph (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256h __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsh_h (__m256h __A) +{ + return __A[0]; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_ph (void const *__P) +{ + return *(const __m256h *) __P; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_ph (void const *__P) +{ + return *(const __m128h *) __P; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_ph (void const *__P) +{ + return *(const __m256h_u *) __P; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_ph (void const *__P) +{ + return *(const __m128h_u *) __P; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_ph (void *__P, __m256h __A) +{ + *(__m256h *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_ph (void *__P, __m128h __A) +{ + *(__m128h *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_ph (void *__P, __m256h __A) +{ + *(__m256h_u *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_ph (void *__P, __m128h __A) +{ + *(__m128h_u *) __P = __A; +} + +/* Create a vector with element 0 as F and the rest zero. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_sh (_Float16 __F) +{ + return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, + __F); +} + +/* Create a vector with element 0 as *P and the rest zero. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_sh (void const *__P) +{ + return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, + *(_Float16 const *) __P); +} + +/* Stores the lower _Float16 value. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_sh (void *__P, __m128h __A) +{ + *(_Float16 *) __P = ((__v8hf)__A)[0]; +} + +/* Intrinsics of v[add,sub,mul,div]sh. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_sh (__m128h __A, __m128h __B) +{ + __A[0] += __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_addsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_addsh_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_sh (__m128h __A, __m128h __B) +{ + __A[0] -= __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_subsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_subsh_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_sh (__m128h __A, __m128h __B) +{ + __A[0] *= __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_mulsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_mulsh_mask (__B, __C, _mm_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_sh (__m128h __A, __m128h __B) +{ + __A[0] /= __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_divsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_divsh_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_addsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_addsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_addsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_subsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_subsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_subsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_mulsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_mulsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_mulsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_divsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_divsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_divsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} +#else +#define _mm_add_round_sh(A, B, C) \ + ((__m128h)__builtin_ia32_addsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_add_round_sh(A, B, C, D, E) \ + ((__m128h)__builtin_ia32_addsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_add_round_sh(A, B, C, D) \ + ((__m128h)__builtin_ia32_addsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) + +#define _mm_sub_round_sh(A, B, C) \ + ((__m128h)__builtin_ia32_subsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_sub_round_sh(A, B, C, D, E) \ + ((__m128h)__builtin_ia32_subsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_sub_round_sh(A, B, C, D) \ + ((__m128h)__builtin_ia32_subsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) + +#define _mm_mul_round_sh(A, B, C) \ + ((__m128h)__builtin_ia32_mulsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_mul_round_sh(A, B, C, D, E) \ + ((__m128h)__builtin_ia32_mulsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_mul_round_sh(A, B, C, D) \ + ((__m128h)__builtin_ia32_mulsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) + +#define _mm_div_round_sh(A, B, C) \ + ((__m128h)__builtin_ia32_divsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_div_round_sh(A, B, C, D, E) \ + ((__m128h)__builtin_ia32_divsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_div_round_sh(A, B, C, D) \ + ((__m128h)__builtin_ia32_divsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) +#endif /* __OPTIMIZE__ */ + +/* Intrinsic vmaxsh vminsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_sh (__m128h __A, __m128h __B) +{ + __A[0] = __A[0] > __B[0] ? __A[0] : __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_maxsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_maxsh_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_sh (__m128h __A, __m128h __B) +{ + __A[0] = __A[0] < __B[0] ? __A[0] : __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_minsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_minsh_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_maxsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_maxsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_maxsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_minsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_minsh_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_minsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +#else +#define _mm_max_round_sh(A, B, C) \ + (__builtin_ia32_maxsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_max_round_sh(A, B, C, D, E) \ + (__builtin_ia32_maxsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_max_round_sh(A, B, C, D) \ + (__builtin_ia32_maxsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) + +#define _mm_min_round_sh(A, B, C) \ + (__builtin_ia32_minsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_min_round_sh(A, B, C, D, E) \ + (__builtin_ia32_minsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_min_round_sh(A, B, C, D) \ + (__builtin_ia32_minsh_mask_round ((B), (C), \ + _mm_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcmpsh. */ +#ifdef __OPTIMIZE__ +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_sh_mask (__m128h __A, __m128h __B, const int __C) +{ + return (__mmask8) + __builtin_ia32_cmpsh_mask_round (__A, __B, + __C, (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_sh_mask (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return (__mmask8) + __builtin_ia32_cmpsh_mask_round (__B, __C, + __D, __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_round_sh_mask (__m128h __A, __m128h __B, const int __C, + const int __D) +{ + return (__mmask8) __builtin_ia32_cmpsh_mask_round (__A, __B, + __C, (__mmask8) -1, + __D); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_round_sh_mask (__mmask8 __A, __m128h __B, __m128h __C, + const int __D, const int __E) +{ + return (__mmask8) __builtin_ia32_cmpsh_mask_round (__B, __C, + __D, __A, + __E); +} + +#else +#define _mm_cmp_sh_mask(A, B, C) \ + (__builtin_ia32_cmpsh_mask_round ((A), (B), (C), (-1), \ + (_MM_FROUND_CUR_DIRECTION))) + +#define _mm_mask_cmp_sh_mask(A, B, C, D) \ + (__builtin_ia32_cmpsh_mask_round ((B), (C), (D), (A), \ + (_MM_FROUND_CUR_DIRECTION))) + +#define _mm_cmp_round_sh_mask(A, B, C, D) \ + (__builtin_ia32_cmpsh_mask_round ((A), (B), (C), (-1), (D))) + +#define _mm_mask_cmp_round_sh_mask(A, B, C, D, E) \ + (__builtin_ia32_cmpsh_mask_round ((B), (C), (D), (A), (E))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcomish. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comieq_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_EQ_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comilt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LT_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comile_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LE_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comigt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GT_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comige_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GE_OS, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comineq_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_NEQ_US, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomieq_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_EQ_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomilt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LT_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomile_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LE_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomigt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GT_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomige_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GE_OQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomineq_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_NEQ_UQ, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comi_sh (__m128h __A, __m128h __B, const int __P) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, __P, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comi_round_sh (__m128h __A, __m128h __B, const int __P, const int __R) +{ + return __builtin_ia32_cmpsh_mask_round (__A, __B, __P, + (__mmask8) -1,__R); +} + +#else +#define _mm_comi_round_sh(A, B, P, R) \ + (__builtin_ia32_cmpsh_mask_round ((A), (B), (P), (__mmask8) (-1), (R))) +#define _mm_comi_sh(A, B, P) \ + (__builtin_ia32_cmpsh_mask_round ((A), (B), (P), (__mmask8) (-1), \ + _MM_FROUND_CUR_DIRECTION)) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vsqrtsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_sqrtsh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_sqrtsh_mask_round (__D, __C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_sqrtsh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_sqrtsh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_sqrtsh_mask_round (__D, __C, __A, __B, + __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_sqrtsh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, __D); +} + +#else +#define _mm_sqrt_round_sh(A, B, C) \ + (__builtin_ia32_sqrtsh_mask_round ((B), (A), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_sqrt_round_sh(A, B, C, D, E) \ + (__builtin_ia32_sqrtsh_mask_round ((D), (C), (A), (B), (E))) + +#define _mm_maskz_sqrt_round_sh(A, B, C, D) \ + (__builtin_ia32_sqrtsh_mask_round ((C), (B), \ + _mm_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vrsqrtsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_rsqrtsh_mask (__B, __A, _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_rsqrtsh_mask (__D, __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_rsqrtsh_mask (__C, __B, _mm_setzero_ph (), + __A); +} + +/* Intrinsics vrcpsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_rcpsh_mask (__B, __A, _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp_sh (__m128h __A, __mmask32 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_rcpsh_mask (__D, __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp_sh (__mmask32 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_rcpsh_mask (__C, __B, _mm_setzero_ph (), + __A); +} + +/* Intrinsics vscalefsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_sh (__m128h __A, __m128h __B) +{ + return __builtin_ia32_scalefsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_scalefsh_mask_round (__C, __D, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_scalefsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_round_sh (__m128h __A, __m128h __B, const int __C) +{ + return __builtin_ia32_scalefsh_mask_round (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1, __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return __builtin_ia32_scalefsh_mask_round (__C, __D, __A, __B, + __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return __builtin_ia32_scalefsh_mask_round (__B, __C, + _mm_setzero_ph (), + __A, __D); +} + +#else +#define _mm_scalef_round_sh(A, B, C) \ + (__builtin_ia32_scalefsh_mask_round ((A), (B), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (C))) + +#define _mm_mask_scalef_round_sh(A, B, C, D, E) \ + (__builtin_ia32_scalefsh_mask_round ((C), (D), (A), (B), (E))) + +#define _mm_maskz_scalef_round_sh(A, B, C, D) \ + (__builtin_ia32_scalefsh_mask_round ((B), (C), _mm_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vreducesh. */ +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_sh (__m128h __A, __m128h __B, int __C) +{ + return __builtin_ia32_reducesh_mask_round (__A, __B, __C, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, int __E) +{ + return __builtin_ia32_reducesh_mask_round (__C, __D, __E, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_sh (__mmask8 __A, __m128h __B, __m128h __C, int __D) +{ + return __builtin_ia32_reducesh_mask_round (__B, __C, __D, + _mm_setzero_ph (), __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_round_sh (__m128h __A, __m128h __B, int __C, const int __D) +{ + return __builtin_ia32_reducesh_mask_round (__A, __B, __C, + _mm_setzero_ph (), + (__mmask8) -1, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, int __E, const int __F) +{ + return __builtin_ia32_reducesh_mask_round (__C, __D, __E, __A, + __B, __F); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + int __D, const int __E) +{ + return __builtin_ia32_reducesh_mask_round (__B, __C, __D, + _mm_setzero_ph (), + __A, __E); +} + +#else +#define _mm_reduce_sh(A, B, C) \ + (__builtin_ia32_reducesh_mask_round ((A), (B), (C), \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_reduce_sh(A, B, C, D, E) \ + (__builtin_ia32_reducesh_mask_round ((C), (D), (E), (A), (B), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_reduce_sh(A, B, C, D) \ + (__builtin_ia32_reducesh_mask_round ((B), (C), (D), \ + _mm_setzero_ph (), \ + (A), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_reduce_round_sh(A, B, C, D) \ + (__builtin_ia32_reducesh_mask_round ((A), (B), (C), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (D))) + +#define _mm_mask_reduce_round_sh(A, B, C, D, E, F) \ + (__builtin_ia32_reducesh_mask_round ((C), (D), (E), (A), (B), (F))) + +#define _mm_maskz_reduce_round_sh(A, B, C, D, E) \ + (__builtin_ia32_reducesh_mask_round ((B), (C), (D), \ + _mm_setzero_ph (), \ + (A), (E))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vrndscalesh. */ +#ifdef __OPTIMIZE__ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_sh (__m128h __A, __m128h __B, int __C) +{ + return __builtin_ia32_rndscalesh_mask_round (__A, __B, __C, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, int __E) +{ + return __builtin_ia32_rndscalesh_mask_round (__C, __D, __E, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_sh (__mmask8 __A, __m128h __B, __m128h __C, int __D) +{ + return __builtin_ia32_rndscalesh_mask_round (__B, __C, __D, + _mm_setzero_ph (), __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_round_sh (__m128h __A, __m128h __B, int __C, const int __D) +{ + return __builtin_ia32_rndscalesh_mask_round (__A, __B, __C, + _mm_setzero_ph (), + (__mmask8) -1, + __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_round_sh (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, int __E, const int __F) +{ + return __builtin_ia32_rndscalesh_mask_round (__C, __D, __E, + __A, __B, __F); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_round_sh (__mmask8 __A, __m128h __B, __m128h __C, + int __D, const int __E) +{ + return __builtin_ia32_rndscalesh_mask_round (__B, __C, __D, + _mm_setzero_ph (), + __A, __E); +} + +#else +#define _mm_roundscale_sh(A, B, C) \ + (__builtin_ia32_rndscalesh_mask_round ((A), (B), (C), \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_roundscale_sh(A, B, C, D, E) \ + (__builtin_ia32_rndscalesh_mask_round ((C), (D), (E), (A), (B), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_roundscale_sh(A, B, C, D) \ + (__builtin_ia32_rndscalesh_mask_round ((B), (C), (D), \ + _mm_setzero_ph (), \ + (A), _MM_FROUND_CUR_DIRECTION)) + +#define _mm_roundscale_round_sh(A, B, C, D) \ + (__builtin_ia32_rndscalesh_mask_round ((A), (B), (C), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (D))) + +#define _mm_mask_roundscale_round_sh(A, B, C, D, E, F) \ + (__builtin_ia32_rndscalesh_mask_round ((C), (D), (E), (A), (B), (F))) + +#define _mm_maskz_roundscale_round_sh(A, B, C, D, E) \ + (__builtin_ia32_rndscalesh_mask_round ((B), (C), (D), \ + _mm_setzero_ph (), \ + (A), (E))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfpclasssh. */ +#ifdef __OPTIMIZE__ +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_sh_mask (__m128h __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) __A, __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fpclass_sh_mask (__mmask8 __U, __m128h __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) __A, __imm, __U); +} + +#else +#define _mm_fpclass_sh_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) (__m128h) (X), \ + (int) (C), (__mmask8) (-1))) \ + +#define _mm_mask_fpclass_sh_mask(U, X, C) \ + ((__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) (__m128h) (X), \ + (int) (C), (__mmask8) (U))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vgetexpsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_sh (__m128h __A, __m128h __B) +{ + return (__m128h) + __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__v8hf) _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) + __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__v8hf) __W, (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_sh (__mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) + __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__v8hf) _mm_setzero_ph (), + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_round_sh (__m128h __A, __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + _mm_setzero_ph (), + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_round_sh (__m128h __W, __mmask8 __U, __m128h __A, + __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __W, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_round_sh (__mmask8 __U, __m128h __A, __m128h __B, + const int __R) +{ + return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) + _mm_setzero_ph (), + (__mmask8) __U, __R); +} + +#else +#define _mm_getexp_round_sh(A, B, R) \ + ((__m128h)__builtin_ia32_getexpsh_mask_round((__v8hf)(__m128h)(A), \ + (__v8hf)(__m128h)(B), \ + (__v8hf)_mm_setzero_ph(), \ + (__mmask8)-1, R)) + +#define _mm_mask_getexp_round_sh(W, U, A, B, C) \ + (__m128h)__builtin_ia32_getexpsh_mask_round(A, B, W, U, C) + +#define _mm_maskz_getexp_round_sh(U, A, B, C) \ + (__m128h)__builtin_ia32_getexpsh_mask_round(A, B, \ + (__v8hf)_mm_setzero_ph(), \ + U, C) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vgetmantsh. */ +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_sh (__m128h __A, __m128h __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128h) + __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__D << 2) | __C, _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_sh (__m128h __W, __mmask8 __U, __m128h __A, + __m128h __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128h) + __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__D << 2) | __C, (__v8hf) __W, + __U, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_sh (__mmask8 __U, __m128h __A, __m128h __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D) +{ + return (__m128h) + __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B, + (__D << 2) | __C, + (__v8hf) _mm_setzero_ph(), + __U, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_round_sh (__m128h __A, __m128h __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + (__D << 2) | __C, + _mm_setzero_ph (), + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_round_sh (__m128h __W, __mmask8 __U, __m128h __A, + __m128h __B, _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + (__D << 2) | __C, + (__v8hf) __W, + __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_round_sh (__mmask8 __U, __m128h __A, __m128h __B, + _MM_MANTISSA_NORM_ENUM __C, + _MM_MANTISSA_SIGN_ENUM __D, const int __R) +{ + return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, + (__v8hf) __B, + (__D << 2) | __C, + (__v8hf) + _mm_setzero_ph(), + __U, __R); +} + +#else +#define _mm_getmant_sh(X, Y, C, D) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h) \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_mask_getmant_sh(W, U, X, Y, C, D) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h)(W), \ + (__mmask8)(U), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_maskz_getmant_sh(U, X, Y, C, D) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h) \ + _mm_setzero_ph(), \ + (__mmask8)(U), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm_getmant_round_sh(X, Y, C, D, R) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h) \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + (R))) + +#define _mm_mask_getmant_round_sh(W, U, X, Y, C, D, R) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h)(W), \ + (__mmask8)(U), \ + (R))) + +#define _mm_maskz_getmant_round_sh(U, X, Y, C, D, R) \ + ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \ + (__v8hf)(__m128h)(Y), \ + (int)(((D)<<2) | (C)), \ + (__v8hf)(__m128h) \ + _mm_setzero_ph(), \ + (__mmask8)(U), \ + (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vmovw. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi16_si128 (short __A) +{ + return _mm_avx512_set_epi16 (0, 0, 0, 0, 0, 0, 0, __A); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi128_si16 (__m128i __A) +{ + return __builtin_ia32_vec_ext_v8hi ((__v8hi)__A, 0); +} + +/* Intrinsics vmovsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_sh (__m128h __A, __mmask8 __B, _Float16 const* __C) +{ + return __builtin_ia32_loadsh_mask (__C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_sh (__mmask8 __A, _Float16 const* __B) +{ + return __builtin_ia32_loadsh_mask (__B, _mm_setzero_ph (), __A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_sh (_Float16 const* __A, __mmask8 __B, __m128h __C) +{ + __builtin_ia32_storesh_mask (__A, __C, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_move_sh (__m128h __A, __m128h __B) +{ + __A[0] = __B[0]; + return __A; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_move_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_vmovsh_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_move_sh (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_vmovsh_mask (__B, __C, _mm_setzero_ph (), __A); +} + +/* Intrinsics vcvtsh2si, vcvtsh2us. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_i32 (__m128h __A) +{ + return (int) __builtin_ia32_vcvtsh2si32_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_u32 (__m128h __A) +{ + return (int) __builtin_ia32_vcvtsh2usi32_round (__A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_i32 (__m128h __A, const int __R) +{ + return (int) __builtin_ia32_vcvtsh2si32_round (__A, __R); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_u32 (__m128h __A, const int __R) +{ + return (int) __builtin_ia32_vcvtsh2usi32_round (__A, __R); +} + +#else +#define _mm_cvt_roundsh_i32(A, B) \ + ((int)__builtin_ia32_vcvtsh2si32_round ((A), (B))) +#define _mm_cvt_roundsh_u32(A, B) \ + ((int)__builtin_ia32_vcvtsh2usi32_round ((A), (B))) + +#endif /* __OPTIMIZE__ */ + +#ifdef __x86_64__ +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_i64 (__m128h __A) +{ + return (long long) + __builtin_ia32_vcvtsh2si64_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_u64 (__m128h __A) +{ + return (long long) + __builtin_ia32_vcvtsh2usi64_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_i64 (__m128h __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtsh2si64_round (__A, __R); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_u64 (__m128h __A, const int __R) +{ + return (long long) __builtin_ia32_vcvtsh2usi64_round (__A, __R); +} + +#else +#define _mm_cvt_roundsh_i64(A, B) \ + ((long long)__builtin_ia32_vcvtsh2si64_round ((A), (B))) +#define _mm_cvt_roundsh_u64(A, B) \ + ((long long)__builtin_ia32_vcvtsh2usi64_round ((A), (B))) + +#endif /* __OPTIMIZE__ */ +#endif /* __x86_64__ */ + +/* Intrinsics vcvtsi2sh, vcvtusi2sh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti32_sh (__m128h __A, int __B) +{ + return __builtin_ia32_vcvtsi2sh32_round (__A, __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu32_sh (__m128h __A, unsigned int __B) +{ + return __builtin_ia32_vcvtusi2sh32_round (__A, __B, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundi32_sh (__m128h __A, int __B, const int __R) +{ + return __builtin_ia32_vcvtsi2sh32_round (__A, __B, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundu32_sh (__m128h __A, unsigned int __B, const int __R) +{ + return __builtin_ia32_vcvtusi2sh32_round (__A, __B, __R); +} + +#else +#define _mm_cvt_roundi32_sh(A, B, C) \ + (__builtin_ia32_vcvtsi2sh32_round ((A), (B), (C))) +#define _mm_cvt_roundu32_sh(A, B, C) \ + (__builtin_ia32_vcvtusi2sh32_round ((A), (B), (C))) + +#endif /* __OPTIMIZE__ */ + +#ifdef __x86_64__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvti64_sh (__m128h __A, long long __B) +{ + return __builtin_ia32_vcvtsi2sh64_round (__A, __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtu64_sh (__m128h __A, unsigned long long __B) +{ + return __builtin_ia32_vcvtusi2sh64_round (__A, __B, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundi64_sh (__m128h __A, long long __B, const int __R) +{ + return __builtin_ia32_vcvtsi2sh64_round (__A, __B, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundu64_sh (__m128h __A, unsigned long long __B, const int __R) +{ + return __builtin_ia32_vcvtusi2sh64_round (__A, __B, __R); +} + +#else +#define _mm_cvt_roundi64_sh(A, B, C) \ + (__builtin_ia32_vcvtsi2sh64_round ((A), (B), (C))) +#define _mm_cvt_roundu64_sh(A, B, C) \ + (__builtin_ia32_vcvtusi2sh64_round ((A), (B), (C))) + +#endif /* __OPTIMIZE__ */ +#endif /* __x86_64__ */ + +/* Intrinsics vcvttsh2si, vcvttsh2us. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsh_i32 (__m128h __A) +{ + return (int) + __builtin_ia32_vcvttsh2si32_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsh_u32 (__m128h __A) +{ + return (int) + __builtin_ia32_vcvttsh2usi32_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsh_i32 (__m128h __A, const int __R) +{ + return (int) __builtin_ia32_vcvttsh2si32_round (__A, __R); +} + +extern __inline unsigned +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsh_u32 (__m128h __A, const int __R) +{ + return (int) __builtin_ia32_vcvttsh2usi32_round (__A, __R); +} + +#else +#define _mm_cvtt_roundsh_i32(A, B) \ + ((int)__builtin_ia32_vcvttsh2si32_round ((A), (B))) +#define _mm_cvtt_roundsh_u32(A, B) \ + ((int)__builtin_ia32_vcvttsh2usi32_round ((A), (B))) + +#endif /* __OPTIMIZE__ */ + +#ifdef __x86_64__ +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsh_i64 (__m128h __A) +{ + return (long long) + __builtin_ia32_vcvttsh2si64_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsh_u64 (__m128h __A) +{ + return (long long) + __builtin_ia32_vcvttsh2usi64_round (__A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsh_i64 (__m128h __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttsh2si64_round (__A, __R); +} + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_roundsh_u64 (__m128h __A, const int __R) +{ + return (long long) __builtin_ia32_vcvttsh2usi64_round (__A, __R); +} + +#else +#define _mm_cvtt_roundsh_i64(A, B) \ + ((long long)__builtin_ia32_vcvttsh2si64_round ((A), (B))) +#define _mm_cvtt_roundsh_u64(A, B) \ + ((long long)__builtin_ia32_vcvttsh2usi64_round ((A), (B))) + +#endif /* __OPTIMIZE__ */ +#endif /* __x86_64__ */ + +/* Intrinsics vcvtsh2ss, vcvtsh2sd. */ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_ss (__m128 __A, __m128h __B) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__B, __A, + _mm_avx512_setzero_ps (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsh_ss (__m128 __A, __mmask8 __B, __m128 __C, + __m128h __D) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__D, __C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsh_ss (__mmask8 __A, __m128 __B, + __m128h __C) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__C, __B, + _mm_avx512_setzero_ps (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_sd (__m128d __A, __m128h __B) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__B, __A, + _mm_avx512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsh_sd (__m128d __A, __mmask8 __B, __m128d __C, + __m128h __D) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__D, __C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsh_sd (__mmask8 __A, __m128d __B, __m128h __C) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__C, __B, + _mm_avx512_setzero_pd (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_ss (__m128 __A, __m128h __B, const int __R) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__B, __A, + _mm_avx512_setzero_ps (), + (__mmask8) -1, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundsh_ss (__m128 __A, __mmask8 __B, __m128 __C, + __m128h __D, const int __R) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__D, __C, __A, __B, __R); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundsh_ss (__mmask8 __A, __m128 __B, + __m128h __C, const int __R) +{ + return __builtin_ia32_vcvtsh2ss_mask_round (__C, __B, + _mm_avx512_setzero_ps (), + __A, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsh_sd (__m128d __A, __m128h __B, const int __R) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__B, __A, + _mm_avx512_setzero_pd (), + (__mmask8) -1, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundsh_sd (__m128d __A, __mmask8 __B, __m128d __C, + __m128h __D, const int __R) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__D, __C, __A, __B, __R); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundsh_sd (__mmask8 __A, __m128d __B, __m128h __C, const int __R) +{ + return __builtin_ia32_vcvtsh2sd_mask_round (__C, __B, + _mm_avx512_setzero_pd (), + __A, __R); +} + +#else +#define _mm_cvt_roundsh_ss(A, B, R) \ + (__builtin_ia32_vcvtsh2ss_mask_round ((B), (A), \ + _mm_avx512_setzero_ps (), \ + (__mmask8) -1, (R))) + +#define _mm_mask_cvt_roundsh_ss(A, B, C, D, R) \ + (__builtin_ia32_vcvtsh2ss_mask_round ((D), (C), (A), (B), (R))) + +#define _mm_maskz_cvt_roundsh_ss(A, B, C, R) \ + (__builtin_ia32_vcvtsh2ss_mask_round ((C), (B), \ + _mm_avx512_setzero_ps (), \ + (A), (R))) + +#define _mm_cvt_roundsh_sd(A, B, R) \ + (__builtin_ia32_vcvtsh2sd_mask_round ((B), (A), \ + _mm_avx512_setzero_pd (), \ + (__mmask8) -1, (R))) + +#define _mm_mask_cvt_roundsh_sd(A, B, C, D, R) \ + (__builtin_ia32_vcvtsh2sd_mask_round ((D), (C), (A), (B), (R))) + +#define _mm_maskz_cvt_roundsh_sd(A, B, C, R) \ + (__builtin_ia32_vcvtsh2sd_mask_round ((C), (B), \ + _mm_avx512_setzero_pd (), \ + (A), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtss2sh, vcvtsd2sh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_sh (__m128h __A, __m128 __B) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtss_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128 __D) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__D, __C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtss_sh (__mmask8 __A, __m128h __B, __m128 __C) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_sh (__m128h __A, __m128d __B) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsd_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128d __D) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__D, __C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsd_sh (__mmask8 __A, __m128h __B, __m128d __C) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundss_sh (__m128h __A, __m128 __B, const int __R) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundss_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128 __D, + const int __R) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__D, __C, __A, __B, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundss_sh (__mmask8 __A, __m128h __B, __m128 __C, + const int __R) +{ + return __builtin_ia32_vcvtss2sh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_roundsd_sh (__m128h __A, __m128d __B, const int __R) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__B, __A, + _mm_setzero_ph (), + (__mmask8) -1, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvt_roundsd_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128d __D, + const int __R) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__D, __C, __A, __B, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvt_roundsd_sh (__mmask8 __A, __m128h __B, __m128d __C, + const int __R) +{ + return __builtin_ia32_vcvtsd2sh_mask_round (__C, __B, + _mm_setzero_ph (), + __A, __R); +} + +#else +#define _mm_cvt_roundss_sh(A, B, R) \ + (__builtin_ia32_vcvtss2sh_mask_round ((B), (A), \ + _mm_setzero_ph (), \ + (__mmask8) -1, R)) + +#define _mm_mask_cvt_roundss_sh(A, B, C, D, R) \ + (__builtin_ia32_vcvtss2sh_mask_round ((D), (C), (A), (B), (R))) + +#define _mm_maskz_cvt_roundss_sh(A, B, C, R) \ + (__builtin_ia32_vcvtss2sh_mask_round ((C), (B), \ + _mm_setzero_ph (), \ + A, R)) + +#define _mm_cvt_roundsd_sh(A, B, R) \ + (__builtin_ia32_vcvtsd2sh_mask_round ((B), (A), \ + _mm_setzero_ph (), \ + (__mmask8) -1, R)) + +#define _mm_mask_cvt_roundsd_sh(A, B, C, D, R) \ + (__builtin_ia32_vcvtsd2sh_mask_round ((D), (C), (A), (B), (R))) + +#define _mm_maskz_cvt_roundsd_sh(A, B, C, R) \ + (__builtin_ia32_vcvtsd2sh_mask_round ((C), (B), \ + _mm_setzero_ph (), \ + (A), (R))) + +#endif /* __OPTIMIZE__ */ + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsh_h (__m128h __A) +{ + return __A[0]; +} + +/* Intrinsics vfmadd[132,213,231]sh. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_sh (__m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_round_sh (__mmask8 __U, __m128h __W, __m128h __A, + __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +#else +#define _mm_fmadd_round_sh(A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), (C), (-1), (R))) +#define _mm_mask_fmadd_round_sh(A, U, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), (C), (U), (R))) +#define _mm_mask3_fmadd_round_sh(A, B, C, U, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask3 ((A), (B), (C), (U), (R))) +#define _mm_maskz_fmadd_round_sh(U, A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfnmadd[132,213,231]sh. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_sh (__m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B, + const int __R) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U, + const int __R) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_round_sh (__mmask8 __U, __m128h __W, __m128h __A, + __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfnmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +#else +#define _mm_fnmadd_round_sh(A, B, C, R) \ + ((__m128h) __builtin_ia32_vfnmaddsh3_mask ((A), (B), (C), (-1), (R))) +#define _mm_mask_fnmadd_round_sh(A, U, B, C, R) \ + ((__m128h) __builtin_ia32_vfnmaddsh3_mask ((A), (B), (C), (U), (R))) +#define _mm_mask3_fnmadd_round_sh(A, B, C, U, R) \ + ((__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((A), (B), (C), (U), (R))) +#define _mm_maskz_fnmadd_round_sh(U, A, B, C, R) \ + ((__m128h) __builtin_ia32_vfnmaddsh3_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfmsub[132,213,231]sh. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_sh (__m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W, + (__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_round_sh (__mmask8 __U, __m128h __W, __m128h __A, + __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + (__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, __R); +} + +#else +#define _mm_fmsub_round_sh(A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), -(C), (-1), (R))) +#define _mm_mask_fmsub_round_sh(A, U, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), -(C), (U), (R))) +#define _mm_mask3_fmsub_round_sh(A, B, C, U, R) \ + ((__m128h) __builtin_ia32_vfmsubsh3_mask3 ((A), (B), (C), (U), (R))) +#define _mm_maskz_fmsub_round_sh(U, A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), (B), -(C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfnmsub[132,213,231]sh. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_sh (__m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W, + -(__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); +} + + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) -1, + __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U, + const int __R) +{ + return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W, + -(__v8hf) __A, + (__v8hf) __B, + (__mmask8) __U, __R); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_round_sh (__mmask8 __U, __m128h __W, __m128h __A, + __m128h __B, const int __R) +{ + return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W, + -(__v8hf) __A, + -(__v8hf) __B, + (__mmask8) __U, __R); +} + +#else +#define _mm_fnmsub_round_sh(A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), -(B), -(C), (-1), (R))) +#define _mm_mask_fnmsub_round_sh(A, U, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), -(B), -(C), (U), (R))) +#define _mm_mask3_fnmsub_round_sh(A, B, C, U, R) \ + ((__m128h) __builtin_ia32_vfmsubsh3_mask3 ((A), -(B), (C), (U), (R))) +#define _mm_maskz_fnmsub_round_sh(U, A, B, C, R) \ + ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), -(B), -(C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vf[,c]maddcsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, __D, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, __D, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_sch (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, + __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + __D, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, + __A, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, + __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + __D, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, + __A, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcsh_round ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + __D); +} +#else +#define _mm_mask_fcmadd_round_sch(A, B, C, D, E) \ + ((__m128h) \ + __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) (A), \ + (__v8hf) (C), \ + (__v8hf) (D), \ + (B), (E))) + + +#define _mm_mask3_fcmadd_round_sch(A, B, C, D, E) \ + ((__m128h) \ + __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) (A), \ + (__v8hf) (B), \ + (__v8hf) (C), \ + (D), (E))) + +#define _mm_maskz_fcmadd_round_sch(A, B, C, D, E) \ + __builtin_ia32_vfcmaddcsh_maskz_round ((B), (C), (D), (A), (E)) + +#define _mm_fcmadd_round_sch(A, B, C, D) \ + __builtin_ia32_vfcmaddcsh_round ((A), (B), (C), (D)) + +#define _mm_mask_fmadd_round_sch(A, B, C, D, E) \ + ((__m128h) \ + __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) (A), \ + (__v8hf) (C), \ + (__v8hf) (D), \ + (B), (E))) + +#define _mm_mask3_fmadd_round_sch(A, B, C, D, E) \ + ((__m128h) \ + __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) (A), \ + (__v8hf) (B), \ + (__v8hf) (C), \ + (D), (E))) + +#define _mm_maskz_fmadd_round_sch(A, B, C, D, E) \ + __builtin_ia32_vfmaddcsh_maskz_round ((B), (C), (D), (A), (E)) + +#define _mm_fmadd_round_sch(A, B, C, D) \ + __builtin_ia32_vfmaddcsh_round ((A), (B), (C), (D)) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vf[,c]mulcsh. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmul_sch (__m128h __A, __m128h __B) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_round ((__v8hf) __A, + (__v8hf) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, + __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmul_sch (__mmask8 __A, __m128h __B, __m128h __C) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmul_sch (__m128h __A, __m128h __B) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_round ((__v8hf) __A, + (__v8hf) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, + __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmul_sch (__mmask8 __A, __m128h __B, __m128h __C) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmul_round_sch (__m128h __A, __m128h __B, const int __D) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_round ((__v8hf) __A, + (__v8hf) __B, + __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, + __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C, + const int __E) +{ + return (__m128h) + __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmul_round_sch (__m128h __A, __m128h __B, const int __D) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_round ((__v8hf) __A, + (__v8hf) __B, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C, + __m128h __D, const int __E) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, + __B, __E); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C, const int __E) +{ + return (__m128h) + __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A, __E); +} + +#else +#define _mm_fcmul_round_sch(__A, __B, __D) \ + (__m128h) __builtin_ia32_vfcmulcsh_round ((__v8hf) __A, \ + (__v8hf) __B, __D) + +#define _mm_mask_fcmul_round_sch(__A, __B, __C, __D, __E) \ + (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C, \ + (__v8hf) __D, \ + (__v8hf) __A, \ + __B, __E) + +#define _mm_maskz_fcmul_round_sch(__A, __B, __C, __E) \ + (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B, \ + (__v8hf) __C, \ + _mm_setzero_ph (), \ + __A, __E) + +#define _mm_fmul_round_sch(__A, __B, __D) \ + (__m128h) __builtin_ia32_vfmulcsh_round ((__v8hf) __A, \ + (__v8hf) __B, __D) + +#define _mm_mask_fmul_round_sch(__A, __B, __C, __D, __E) \ + (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C, \ + (__v8hf) __D, \ + (__v8hf) __A, \ + __B, __E) + +#define _mm_maskz_fmul_round_sch(__A, __B, __C, __E) \ + (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B, \ + (__v8hf) __C, \ + _mm_setzero_ph (), \ + __A, __E) + +#endif /* __OPTIMIZE__ */ + +#define _mm_mul_sch(A, B) _mm_fmul_sch ((A), (B)) +#define _mm_mask_mul_sch(W, U, A, B) _mm_mask_fmul_sch ((W), (U), (A), (B)) +#define _mm_maskz_mul_sch(U, A, B) _mm_maskz_fmul_sch ((U), (A), (B)) +#define _mm_mul_round_sch(A, B, R) _mm_fmul_round_sch ((A), (B), (R)) +#define _mm_mask_mul_round_sch(W, U, A, B, R) \ + _mm_mask_fmul_round_sch ((W), (U), (A), (B), (R)) +#define _mm_maskz_mul_round_sch(U, A, B, R) \ + _mm_maskz_fmul_round_sch ((U), (A), (B), (R)) + +#define _mm_cmul_sch(A, B) _mm_fcmul_sch ((A), (B)) +#define _mm_mask_cmul_sch(W, U, A, B) _mm_mask_fcmul_sch ((W), (U), (A), (B)) +#define _mm_maskz_cmul_sch(U, A, B) _mm_maskz_fcmul_sch ((U), (A), (B)) +#define _mm_cmul_round_sch(A, B, R) _mm_fcmul_round_sch ((A), (B), (R)) +#define _mm_mask_cmul_round_sch(W, U, A, B, R) \ + _mm_mask_fcmul_round_sch ((W), (U), (A), (B), (R)) +#define _mm_maskz_cmul_round_sch(U, A, B, R) \ + _mm_maskz_fcmul_round_sch ((U), (A), (B), (R)) + +#ifdef __DISABLE_AVX512FP16__ +#undef __DISABLE_AVX512FP16__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512FP16__ */ + +#if !defined (__AVX512FP16__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512fp16,evex512") +#define __DISABLE_AVX512FP16_512__ +#endif /* __AVX512FP16_512__ */ + +typedef _Float16 __v32hf __attribute__ ((__vector_size__ (64))); +typedef _Float16 __m512h __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef _Float16 __m512h_u __attribute__ ((__vector_size__ (64), \ + __may_alias__, __aligned__ (1))); + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set_ph (_Float16 __A31, _Float16 __A30, _Float16 __A29, + _Float16 __A28, _Float16 __A27, _Float16 __A26, + _Float16 __A25, _Float16 __A24, _Float16 __A23, + _Float16 __A22, _Float16 __A21, _Float16 __A20, + _Float16 __A19, _Float16 __A18, _Float16 __A17, + _Float16 __A16, _Float16 __A15, _Float16 __A14, + _Float16 __A13, _Float16 __A12, _Float16 __A11, + _Float16 __A10, _Float16 __A9, _Float16 __A8, + _Float16 __A7, _Float16 __A6, _Float16 __A5, + _Float16 __A4, _Float16 __A3, _Float16 __A2, + _Float16 __A1, _Float16 __A0) +{ + return __extension__ (__m512h)(__v32hf){ __A0, __A1, __A2, __A3, + __A4, __A5, __A6, __A7, + __A8, __A9, __A10, __A11, + __A12, __A13, __A14, __A15, + __A16, __A17, __A18, __A19, + __A20, __A21, __A22, __A23, + __A24, __A25, __A26, __A27, + __A28, __A29, __A30, __A31 }; +} + +/* Create vectors of elements in the reversed order from + _mm512_set_ph functions. */ + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2, + _Float16 __A3, _Float16 __A4, _Float16 __A5, + _Float16 __A6, _Float16 __A7, _Float16 __A8, + _Float16 __A9, _Float16 __A10, _Float16 __A11, + _Float16 __A12, _Float16 __A13, _Float16 __A14, + _Float16 __A15, _Float16 __A16, _Float16 __A17, + _Float16 __A18, _Float16 __A19, _Float16 __A20, + _Float16 __A21, _Float16 __A22, _Float16 __A23, + _Float16 __A24, _Float16 __A25, _Float16 __A26, + _Float16 __A27, _Float16 __A28, _Float16 __A29, + _Float16 __A30, _Float16 __A31) + +{ + return _mm512_set_ph (__A31, __A30, __A29, __A28, __A27, __A26, __A25, + __A24, __A23, __A22, __A21, __A20, __A19, __A18, + __A17, __A16, __A15, __A14, __A13, __A12, __A11, + __A10, __A9, __A8, __A7, __A6, __A5, __A4, __A3, + __A2, __A1, __A0); +} + +/* Broadcast _Float16 to vector. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_ph (_Float16 __A) +{ + return _mm512_set_ph (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +/* Create a vector with all zeros. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_setzero_ph (void) +{ + return _mm512_set1_ph (0.0f16); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_undefined_ph (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m512h __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtsh_h (__m512h __A) +{ + return __A[0]; +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph_ps (__m512h __a) +{ + return (__m512) __a; +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph_pd (__m512h __a) +{ + return (__m512d) __a; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph_si512 (__m512h __a) +{ + return (__m512i) __a; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph512_ph128 (__m512h __A) +{ + union + { + __m128h __a[4]; + __m512h __v; + } __u = { .__v = __A }; + return __u.__a[0]; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph512_ph256 (__m512h __A) +{ + union + { + __m256h __a[2]; + __m512h __v; + } __u = { .__v = __A }; + return __u.__a[0]; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph128_ph512 (__m128h __A) +{ + union + { + __m128h __a[4]; + __m512h __v; + } __u; + __u.__a[0] = __A; + return __u.__v; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castph256_ph512 (__m256h __A) +{ + union + { + __m256h __a[2]; + __m512h __v; + } __u; + __u.__a[0] = __A; + return __u.__v; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextph128_ph512 (__m128h __A) +{ + return (__m512h) _mm512_insertf32x4 (_mm512_setzero_ps (), + (__m128) __A, 0); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_zextph256_ph512 (__m256h __A) +{ + return (__m512h) _mm512_insertf64x4 (_mm512_setzero_pd (), + (__m256d) __A, 0); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castps_ph (__m512 __a) +{ + return (__m512h) __a; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castpd_ph (__m512d __a) +{ + return (__m512h) __a; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_castsi512_ph (__m512i __a) +{ + return (__m512h) __a; +} + +/* Create a vector with element 0 as *P and the rest zero. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_load_ph (void const *__P) +{ + return *(const __m512h *) __P; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_ph (void const *__P) +{ + return *(const __m512h_u *) __P; +} + +/* Stores the lower _Float16 value. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_store_ph (void *__P, __m512h __A) +{ + *(__m512h *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_ph (void *__P, __m512h __A) +{ + *(__m512h_u *) __P = __A; +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_abs_ph (__m512h __A) +{ + return (__m512h) _mm512_and_epi32 ( _mm512_set1_epi32 (0x7FFF7FFF), + (__m512i) __A); +} + +/* Intrinsics v[add,sub,mul,div]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_ph (__m512h __A, __m512h __B) +{ + return (__m512h) ((__v32hf) __A + (__v32hf) __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_addph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_addph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_ph (__m512h __A, __m512h __B) +{ + return (__m512h) ((__v32hf) __A - (__v32hf) __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_subph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_subph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_ph (__m512h __A, __m512h __B) +{ + return (__m512h) ((__v32hf) __A * (__v32hf) __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_mulph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_mulph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_ph (__m512h __A, __m512h __B) +{ + return (__m512h) ((__v32hf) __A / (__v32hf) __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_divph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_divph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_add_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_addph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_add_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_addph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_add_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_addph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sub_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_subph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sub_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_subph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sub_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_subph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mul_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_mulph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_mul_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_mulph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_mul_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_mulph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_div_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_divph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_div_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_divph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_div_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_divph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} +#else +#define _mm512_add_round_ph(A, B, C) \ + ((__m512h)__builtin_ia32_addph512_mask_round((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_add_round_ph(A, B, C, D, E) \ + ((__m512h)__builtin_ia32_addph512_mask_round((C), (D), (A), (B), (E))) + +#define _mm512_maskz_add_round_ph(A, B, C, D) \ + ((__m512h)__builtin_ia32_addph512_mask_round((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#define _mm512_sub_round_ph(A, B, C) \ + ((__m512h)__builtin_ia32_subph512_mask_round((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_sub_round_ph(A, B, C, D, E) \ + ((__m512h)__builtin_ia32_subph512_mask_round((C), (D), (A), (B), (E))) + +#define _mm512_maskz_sub_round_ph(A, B, C, D) \ + ((__m512h)__builtin_ia32_subph512_mask_round((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#define _mm512_mul_round_ph(A, B, C) \ + ((__m512h)__builtin_ia32_mulph512_mask_round((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_mul_round_ph(A, B, C, D, E) \ + ((__m512h)__builtin_ia32_mulph512_mask_round((C), (D), (A), (B), (E))) + +#define _mm512_maskz_mul_round_ph(A, B, C, D) \ + ((__m512h)__builtin_ia32_mulph512_mask_round((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#define _mm512_div_round_ph(A, B, C) \ + ((__m512h)__builtin_ia32_divph512_mask_round((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_div_round_ph(A, B, C, D, E) \ + ((__m512h)__builtin_ia32_divph512_mask_round((C), (D), (A), (B), (E))) + +#define _mm512_maskz_div_round_ph(A, B, C, D) \ + ((__m512h)__builtin_ia32_divph512_mask_round((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) +#endif /* __OPTIMIZE__ */ + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_conj_pch (__m512h __A) +{ + return (__m512h) _mm512_xor_epi32 ((__m512i) __A, _mm512_set1_epi32 (1<<31)); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_conj_pch (__m512h __W, __mmask16 __U, __m512h __A) +{ + return (__m512h) + __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A), + (__v16sf) __W, + (__mmask16) __U); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_conj_pch (__mmask16 __U, __m512h __A) +{ + return (__m512h) + __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A), + (__v16sf) _mm512_setzero_ps (), + (__mmask16) __U); +} + +/* Intrinsic vmaxph vminph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_ph (__m512h __A, __m512h __B) +{ + return __builtin_ia32_maxph512_mask (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_maxph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_maxph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_ph (__m512h __A, __m512h __B) +{ + return __builtin_ia32_minph512_mask (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_minph512_mask (__C, __D, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_minph512_mask (__B, __C, + _mm512_setzero_ph (), __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_max_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_maxph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_max_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_maxph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_max_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_maxph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_min_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_minph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_min_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_minph512_mask_round (__C, __D, __A, __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_min_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_minph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +#else +#define _mm512_max_round_ph(A, B, C) \ + (__builtin_ia32_maxph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_max_round_ph(A, B, C, D, E) \ + (__builtin_ia32_maxph512_mask_round ((C), (D), (A), (B), (E))) + +#define _mm512_maskz_max_round_ph(A, B, C, D) \ + (__builtin_ia32_maxph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#define _mm512_min_round_ph(A, B, C) \ + (__builtin_ia32_minph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_min_round_ph(A, B, C, D, E) \ + (__builtin_ia32_minph512_mask_round ((C), (D), (A), (B), (E))) + +#define _mm512_maskz_min_round_ph(A, B, C, D) \ + (__builtin_ia32_minph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) +#endif /* __OPTIMIZE__ */ + +/* vcmpph */ +#ifdef __OPTIMIZE +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_ph_mask (__m512h __A, __m512h __B, const int __C) +{ + return (__mmask32) __builtin_ia32_cmpph512_mask (__A, __B, __C, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_ph_mask (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return (__mmask32) __builtin_ia32_cmpph512_mask (__B, __C, __D, + __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cmp_round_ph_mask (__m512h __A, __m512h __B, const int __C, + const int __D) +{ + return (__mmask32) __builtin_ia32_cmpph512_mask_round (__A, __B, + __C, (__mmask32) -1, + __D); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cmp_round_ph_mask (__mmask32 __A, __m512h __B, __m512h __C, + const int __D, const int __E) +{ + return (__mmask32) __builtin_ia32_cmpph512_mask_round (__B, __C, + __D, __A, + __E); +} + +#else +#define _mm512_cmp_ph_mask(A, B, C) \ + (__builtin_ia32_cmpph512_mask ((A), (B), (C), (-1))) + +#define _mm512_mask_cmp_ph_mask(A, B, C, D) \ + (__builtin_ia32_cmpph512_mask ((B), (C), (D), (A))) + +#define _mm512_cmp_round_ph_mask(A, B, C, D) \ + (__builtin_ia32_cmpph512_mask_round ((A), (B), (C), (-1), (D))) + +#define _mm512_mask_cmp_round_ph_mask(A, B, C, D, E) \ + (__builtin_ia32_cmpph512_mask_round ((B), (C), (D), (A), (E))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vsqrtph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_ph (__m512h __A) +{ + return __builtin_ia32_sqrtph512_mask_round (__A, + _mm512_setzero_ph(), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_ph (__m512h __A, __mmask32 __B, __m512h __C) +{ + return __builtin_ia32_sqrtph512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_ph (__mmask32 __A, __m512h __B) +{ + return __builtin_ia32_sqrtph512_mask_round (__B, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_sqrt_round_ph (__m512h __A, const int __B) +{ + return __builtin_ia32_sqrtph512_mask_round (__A, + _mm512_setzero_ph(), + (__mmask32) -1, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_sqrt_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_sqrtph512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_sqrt_round_ph (__mmask32 __A, __m512h __B, const int __C) +{ + return __builtin_ia32_sqrtph512_mask_round (__B, + _mm512_setzero_ph (), + __A, __C); +} + +#else +#define _mm512_sqrt_round_ph(A, B) \ + (__builtin_ia32_sqrtph512_mask_round ((A), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (B))) + +#define _mm512_mask_sqrt_round_ph(A, B, C, D) \ + (__builtin_ia32_sqrtph512_mask_round ((C), (A), (B), (D))) + +#define _mm512_maskz_sqrt_round_ph(A, B, C) \ + (__builtin_ia32_sqrtph512_mask_round ((B), \ + _mm512_setzero_ph (), \ + (A), (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vrsqrtph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rsqrt_ph (__m512h __A) +{ + return __builtin_ia32_rsqrtph512_mask (__A, _mm512_setzero_ph (), + (__mmask32) -1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rsqrt_ph (__m512h __A, __mmask32 __B, __m512h __C) +{ + return __builtin_ia32_rsqrtph512_mask (__C, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rsqrt_ph (__mmask32 __A, __m512h __B) +{ + return __builtin_ia32_rsqrtph512_mask (__B, _mm512_setzero_ph (), + __A); +} + +/* Intrinsics vrcpph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_rcp_ph (__m512h __A) +{ + return __builtin_ia32_rcpph512_mask (__A, _mm512_setzero_ph (), + (__mmask32) -1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_rcp_ph (__m512h __A, __mmask32 __B, __m512h __C) +{ + return __builtin_ia32_rcpph512_mask (__C, __A, __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_rcp_ph (__mmask32 __A, __m512h __B) +{ + return __builtin_ia32_rcpph512_mask (__B, _mm512_setzero_ph (), + __A); +} + +/* Intrinsics vscalefph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_ph (__m512h __A, __m512h __B) +{ + return __builtin_ia32_scalefph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D) +{ + return __builtin_ia32_scalefph512_mask_round (__C, __D, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_ph (__mmask32 __A, __m512h __B, __m512h __C) +{ + return __builtin_ia32_scalefph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_scalef_round_ph (__m512h __A, __m512h __B, const int __C) +{ + return __builtin_ia32_scalefph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_scalef_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + __m512h __D, const int __E) +{ + return __builtin_ia32_scalefph512_mask_round (__C, __D, __A, __B, + __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_scalef_round_ph (__mmask32 __A, __m512h __B, __m512h __C, + const int __D) +{ + return __builtin_ia32_scalefph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +#else +#define _mm512_scalef_round_ph(A, B, C) \ + (__builtin_ia32_scalefph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_scalef_round_ph(A, B, C, D, E) \ + (__builtin_ia32_scalefph512_mask_round ((C), (D), (A), (B), (E))) + +#define _mm512_maskz_scalef_round_ph(A, B, C, D) \ + (__builtin_ia32_scalefph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vreduceph. */ +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_ph (__m512h __A, int __B) +{ + return __builtin_ia32_reduceph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_ph (__m512h __A, __mmask32 __B, __m512h __C, int __D) +{ + return __builtin_ia32_reduceph512_mask_round (__C, __D, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_ph (__mmask32 __A, __m512h __B, int __C) +{ + return __builtin_ia32_reduceph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_round_ph (__m512h __A, int __B, const int __C) +{ + return __builtin_ia32_reduceph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_reduce_round_ph (__m512h __A, __mmask32 __B, __m512h __C, + int __D, const int __E) +{ + return __builtin_ia32_reduceph512_mask_round (__C, __D, __A, __B, + __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_reduce_round_ph (__mmask32 __A, __m512h __B, int __C, + const int __D) +{ + return __builtin_ia32_reduceph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +#else +#define _mm512_reduce_ph(A, B) \ + (__builtin_ia32_reduceph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_reduce_ph(A, B, C, D) \ + (__builtin_ia32_reduceph512_mask_round ((C), (D), (A), (B), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_reduce_ph(A, B, C) \ + (__builtin_ia32_reduceph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_reduce_round_ph(A, B, C) \ + (__builtin_ia32_reduceph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_reduce_round_ph(A, B, C, D, E) \ + (__builtin_ia32_reduceph512_mask_round ((C), (D), (A), (B), (E))) + +#define _mm512_maskz_reduce_round_ph(A, B, C, D) \ + (__builtin_ia32_reduceph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vrndscaleph. */ +#ifdef __OPTIMIZE__ +extern __inline __m512h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_ph (__m512h __A, int __B) +{ + return __builtin_ia32_rndscaleph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_ph (__m512h __A, __mmask32 __B, + __m512h __C, int __D) +{ + return __builtin_ia32_rndscaleph512_mask_round (__C, __D, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_ph (__mmask32 __A, __m512h __B, int __C) +{ + return __builtin_ia32_rndscaleph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_roundscale_round_ph (__m512h __A, int __B, const int __C) +{ + return __builtin_ia32_rndscaleph512_mask_round (__A, __B, + _mm512_setzero_ph (), + (__mmask32) -1, + __C); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_roundscale_round_ph (__m512h __A, __mmask32 __B, + __m512h __C, int __D, const int __E) +{ + return __builtin_ia32_rndscaleph512_mask_round (__C, __D, __A, + __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_roundscale_round_ph (__mmask32 __A, __m512h __B, int __C, + const int __D) +{ + return __builtin_ia32_rndscaleph512_mask_round (__B, __C, + _mm512_setzero_ph (), + __A, __D); +} + +#else +#define _mm512_roundscale_ph(A, B) \ + (__builtin_ia32_rndscaleph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_roundscale_ph(A, B, C, D) \ + (__builtin_ia32_rndscaleph512_mask_round ((C), (D), (A), (B), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_maskz_roundscale_ph(A, B, C) \ + (__builtin_ia32_rndscaleph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), \ + _MM_FROUND_CUR_DIRECTION)) +#define _mm512_roundscale_round_ph(A, B, C) \ + (__builtin_ia32_rndscaleph512_mask_round ((A), (B), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, (C))) + +#define _mm512_mask_roundscale_round_ph(A, B, C, D, E) \ + (__builtin_ia32_rndscaleph512_mask_round ((C), (D), (A), (B), (E))) + +#define _mm512_maskz_roundscale_round_ph(A, B, C, D) \ + (__builtin_ia32_rndscaleph512_mask_round ((B), (C), \ + _mm512_setzero_ph (), \ + (A), (D))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfpclassph. */ +#ifdef __OPTIMIZE__ +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fpclass_ph_mask (__mmask32 __U, __m512h __A, + const int __imm) +{ + return (__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) __A, + __imm, __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fpclass_ph_mask (__m512h __A, const int __imm) +{ + return (__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) __A, + __imm, + (__mmask32) -1); +} + +#else +#define _mm512_mask_fpclass_ph_mask(u, x, c) \ + ((__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) (__m512h) (x), \ + (int) (c),(__mmask8)(u))) + +#define _mm512_fpclass_ph_mask(x, c) \ + ((__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) (__m512h) (x), \ + (int) (c),(__mmask8)-1)) +#endif /* __OPIMTIZE__ */ + +/* Intrinsics vgetexpph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_ph (__m512h __A) +{ + return (__m512h) + __builtin_ia32_getexpph512_mask ((__v32hf) __A, + (__v32hf) _mm512_setzero_ph (), + (__mmask32) -1, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_ph (__m512h __W, __mmask32 __U, __m512h __A) +{ + return (__m512h) + __builtin_ia32_getexpph512_mask ((__v32hf) __A, (__v32hf) __W, + (__mmask32) __U, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_ph (__mmask32 __U, __m512h __A) +{ + return (__m512h) + __builtin_ia32_getexpph512_mask ((__v32hf) __A, + (__v32hf) _mm512_setzero_ph (), + (__mmask32) __U, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getexp_round_ph (__m512h __A, const int __R) +{ + return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A, + (__v32hf) + _mm512_setzero_ph (), + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getexp_round_ph (__m512h __W, __mmask32 __U, __m512h __A, + const int __R) +{ + return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A, + (__v32hf) __W, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getexp_round_ph (__mmask32 __U, __m512h __A, const int __R) +{ + return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A, + (__v32hf) + _mm512_setzero_ph (), + (__mmask32) __U, __R); +} + +#else +#define _mm512_getexp_round_ph(A, R) \ + ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \ + (__v32hf)_mm512_setzero_ph(), (__mmask32)-1, R)) + +#define _mm512_mask_getexp_round_ph(W, U, A, R) \ + ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \ + (__v32hf)(__m512h)(W), (__mmask32)(U), R)) + +#define _mm512_maskz_getexp_round_ph(U, A, R) \ + ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \ + (__v32hf)_mm512_setzero_ph(), (__mmask32)(U), R)) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vgetmantph. */ +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_ph (__m512h __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_ph (__m512h __W, __mmask32 __U, __m512h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + (__v32hf) __W, __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_ph (__mmask32 __U, __m512h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + (__v32hf) + _mm512_setzero_ph (), + __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_getmant_round_ph (__m512h __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + _mm512_setzero_ph (), + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_getmant_round_ph (__m512h __W, __mmask32 __U, __m512h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + (__v32hf) __W, __U, + __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_getmant_round_ph (__mmask32 __U, __m512h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C, const int __R) +{ + return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A, + (__C << 2) | __B, + (__v32hf) + _mm512_setzero_ph (), + __U, __R); +} + +#else +#define _mm512_getmant_ph(X, B, C) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h) \ + _mm512_setzero_ph(), \ + (__mmask32)-1, \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_mask_getmant_ph(W, U, X, B, C) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h)(W), \ + (__mmask32)(U), \ + _MM_FROUND_CUR_DIRECTION)) + + +#define _mm512_maskz_getmant_ph(U, X, B, C) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h) \ + _mm512_setzero_ph(), \ + (__mmask32)(U), \ + _MM_FROUND_CUR_DIRECTION)) + +#define _mm512_getmant_round_ph(X, B, C, R) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h) \ + _mm512_setzero_ph(), \ + (__mmask32)-1, \ + (R))) + +#define _mm512_mask_getmant_round_ph(W, U, X, B, C, R) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h)(W), \ + (__mmask32)(U), \ + (R))) + + +#define _mm512_maskz_getmant_round_ph(U, X, B, C, R) \ + ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \ + (int)(((C)<<2) | (B)), \ + (__v32hf)(__m512h) \ + _mm512_setzero_ph(), \ + (__mmask32)(U), \ + (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2dq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epi32 (__m256h __A) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epi32 (__m512i __A, __mmask16 __B, __m256h __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__C, + (__v16si) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epi32 (__mmask16 __A, __m256h __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epi32 (__m256h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epi32 (__m512i __A, __mmask16 __B, __m256h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__C, + (__v16si) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epi32 (__mmask16 __A, __m256h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2dq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epi32(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvtph2dq512_mask_round ((A), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (__mmask16)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_epi32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvtph2dq512_mask_round ((C), (__v16si)(A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_epi32(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvtph2dq512_mask_round ((B), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2udq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epu32 (__m256h __A) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epu32 (__m512i __A, __mmask16 __B, __m256h __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__C, + (__v16si) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epu32 (__mmask16 __A, __m256h __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epu32 (__m256h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epu32 (__m512i __A, __mmask16 __B, __m256h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__C, + (__v16si) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epu32 (__mmask16 __A, __m256h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2udq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epu32(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvtph2udq512_mask_round ((A), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (__mmask16)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_epu32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvtph2udq512_mask_round ((C), (__v16si)(A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_epu32(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvtph2udq512_mask_round ((B), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2dq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epi32 (__m256h __A) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epi32 (__m512i __A, __mmask16 __B, __m256h __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__C, + (__v16si) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epi32 (__mmask16 __A, __m256h __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epi32 (__m256h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epi32 (__m512i __A, __mmask16 __B, + __m256h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__C, + (__v16si) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epi32 (__mmask16 __A, __m256h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2dq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epi32(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvttph2dq512_mask_round ((A), \ + (__v16si) \ + (_mm512_setzero_si512 ()), \ + (__mmask16)(-1), (B))) + +#define _mm512_mask_cvtt_roundph_epi32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvttph2dq512_mask_round ((C), \ + (__v16si)(A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvtt_roundph_epi32(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvttph2dq512_mask_round ((B), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2udq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epu32 (__m256h __A) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epu32 (__m512i __A, __mmask16 __B, __m256h __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__C, + (__v16si) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epu32 (__mmask16 __A, __m256h __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epu32 (__m256h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epu32 (__m512i __A, __mmask16 __B, + __m256h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__C, + (__v16si) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epu32 (__mmask16 __A, __m256h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2udq512_mask_round (__B, + (__v16si) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epu32(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvttph2udq512_mask_round ((A), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (__mmask16)-1, \ + (B))) + +#define _mm512_mask_cvtt_roundph_epu32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvttph2udq512_mask_round ((C), \ + (__v16si)(A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvtt_roundph_epu32(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvttph2udq512_mask_round ((B), \ + (__v16si) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtdq2ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi32_ph (__m512i __A) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi32_ph (__m256h __A, __mmask16 __B, __m512i __C) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi32_ph (__mmask16 __A, __m512i __B) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __B, + _mm256_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi32_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi32_ph (__m256h __A, __mmask16 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __C, + __A, + __B, + __D); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi32_ph (__mmask16 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __B, + _mm256_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepi32_ph(A, B) \ + (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(A), \ + _mm256_setzero_ph (), \ + (__mmask16)-1, \ + (B))) + +#define _mm512_mask_cvt_roundepi32_ph(A, B, C, D) \ + (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(C), \ + (A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvt_roundepi32_ph(A, B, C) \ + (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(B), \ + _mm256_setzero_ph (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtudq2ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu32_ph (__m512i __A) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu32_ph (__m256h __A, __mmask16 __B, __m512i __C) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu32_ph (__mmask16 __A, __m512i __B) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __B, + _mm256_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu32_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu32_ph (__m256h __A, __mmask16 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __C, + __A, + __B, + __D); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu32_ph (__mmask16 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __B, + _mm256_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepu32_ph(A, B) \ + (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)(A), \ + _mm256_setzero_ph (), \ + (__mmask16)-1, \ + B)) + +#define _mm512_mask_cvt_roundepu32_ph(A, B, C, D) \ + (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)C, \ + A, \ + B, \ + D)) + +#define _mm512_maskz_cvt_roundepu32_ph(A, B, C) \ + (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)B, \ + _mm256_setzero_ph (), \ + A, \ + C)) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2qq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epi64 (__m128h __A) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epi64 (__m512i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epi64 (__m128h __A, int __B) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epi64 (__m512i __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epi64 (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_vcvtph2qq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epi64(A, B) \ + (__builtin_ia32_vcvtph2qq512_mask_round ((A), \ + _mm512_setzero_si512 (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_epi64(A, B, C, D) \ + (__builtin_ia32_vcvtph2qq512_mask_round ((C), (A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_epi64(A, B, C) \ + (__builtin_ia32_vcvtph2qq512_mask_round ((B), \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2uqq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epu64 (__m512i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epu64 (__m128h __A, int __B) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epu64 (__m512i __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epu64 (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_vcvtph2uqq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epu64(A, B) \ + (__builtin_ia32_vcvtph2uqq512_mask_round ((A), \ + _mm512_setzero_si512 (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_epu64(A, B, C, D) \ + (__builtin_ia32_vcvtph2uqq512_mask_round ((C), (A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_epu64(A, B, C) \ + (__builtin_ia32_vcvtph2uqq512_mask_round ((B), \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2qq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epi64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epi64 (__m512i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epi64 (__m128h __A, int __B) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epi64 (__m512i __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epi64 (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_vcvttph2qq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epi64(A, B) \ + (__builtin_ia32_vcvttph2qq512_mask_round ((A), \ + _mm512_setzero_si512 (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvtt_roundph_epi64(A, B, C, D) \ + __builtin_ia32_vcvttph2qq512_mask_round ((C), (A), (B), (D)) + +#define _mm512_maskz_cvtt_roundph_epi64(A, B, C) \ + (__builtin_ia32_vcvttph2qq512_mask_round ((B), \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2uqq. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epu64 (__m512i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epu64 (__m128h __A, int __B) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__A, + _mm512_setzero_si512 (), + (__mmask8) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epu64 (__m512i __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epu64 (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_vcvttph2uqq512_mask_round (__B, + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epu64(A, B) \ + (__builtin_ia32_vcvttph2uqq512_mask_round ((A), \ + _mm512_setzero_si512 (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvtt_roundph_epu64(A, B, C, D) \ + __builtin_ia32_vcvttph2uqq512_mask_round ((C), (A), (B), (D)) + +#define _mm512_maskz_cvtt_roundph_epu64(A, B, C) \ + (__builtin_ia32_vcvttph2uqq512_mask_round ((B), \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtqq2ph. */ +extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi64_ph (__m512i __A) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m512i __C) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi64_ph (__mmask8 __A, __m512i __B) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __B, + _mm_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi64_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __A, + _mm_setzero_ph (), + (__mmask8) -1, + __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi64_ph (__m128h __A, __mmask8 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __C, + __A, + __B, + __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi64_ph (__mmask8 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __B, + _mm_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepi64_ph(A, B) \ + (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(A), \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvt_roundepi64_ph(A, B, C, D) \ + (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(C), (A), (B), (D))) + +#define _mm512_maskz_cvt_roundepi64_ph(A, B, C) \ + (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(B), \ + _mm_setzero_ph (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtuqq2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepu64_ph (__m512i __A) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m512i __C) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu64_ph (__mmask8 __A, __m512i __B) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __B, + _mm_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu64_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __A, + _mm_setzero_ph (), + (__mmask8) -1, + __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu64_ph (__m128h __A, __mmask8 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __C, + __A, + __B, + __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu64_ph (__mmask8 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __B, + _mm_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepu64_ph(A, B) \ + (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(A), \ + _mm_setzero_ph (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvt_roundepu64_ph(A, B, C, D) \ + (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(C), (A), (B), (D))) + +#define _mm512_maskz_cvt_roundepu64_ph(A, B, C) \ + (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(B), \ + _mm_setzero_ph (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2w. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epi16 (__m512h __A) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epi16 (__m512i __A, __mmask32 __B, __m512h __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__C, + (__v32hi) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epi16 (__mmask32 __A, __m512h __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epi16 (__m512h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epi16 (__m512i __A, __mmask32 __B, __m512h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__C, + (__v32hi) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epi16 (__mmask32 __A, __m512h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2w512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epi16(A, B) \ + ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((A), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_epi16(A, B, C, D) \ + ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((C), \ + (__v32hi)(A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvt_roundph_epi16(A, B, C) \ + ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((B), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2uw. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_epu16 (__m512h __A) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_epu16 (__m512i __A, __mmask32 __B, __m512h __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__C, (__v32hi) __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_epu16 (__mmask32 __A, __m512h __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_epu16 (__m512h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_epu16 (__m512i __A, __mmask32 __B, __m512h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__C, (__v32hi) __A, __B, __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_epu16 (__mmask32 __A, __m512h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvtph2uw512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_epu16(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvtph2uw512_mask_round ((A), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1, (B))) + +#define _mm512_mask_cvt_roundph_epu16(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvtph2uw512_mask_round ((C), (__v32hi)(A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_epu16(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvtph2uw512_mask_round ((B), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2w. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epi16 (__m512h __A) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epi16 (__m512i __A, __mmask32 __B, __m512h __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__C, + (__v32hi) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epi16 (__mmask32 __A, __m512h __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epi16 (__m512h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epi16 (__m512i __A, __mmask32 __B, + __m512h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__C, + (__v32hi) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epi16 (__mmask32 __A, __m512h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2w512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epi16(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvttph2w512_mask_round ((A), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1, \ + (B))) + +#define _mm512_mask_cvtt_roundph_epi16(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvttph2w512_mask_round ((C), \ + (__v32hi)(A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvtt_roundph_epi16(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvttph2w512_mask_round ((B), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvttph2uw. */ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvttph_epu16 (__m512h __A) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvttph_epu16 (__m512i __A, __mmask32 __B, __m512h __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__C, + (__v32hi) __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvttph_epu16 (__mmask32 __A, __m512h __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtt_roundph_epu16 (__m512h __A, int __B) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__A, + (__v32hi) + _mm512_setzero_si512 (), + (__mmask32) -1, + __B); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtt_roundph_epu16 (__m512i __A, __mmask32 __B, + __m512h __C, int __D) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__C, + (__v32hi) __A, + __B, + __D); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtt_roundph_epu16 (__mmask32 __A, __m512h __B, int __C) +{ + return (__m512i) + __builtin_ia32_vcvttph2uw512_mask_round (__B, + (__v32hi) + _mm512_setzero_si512 (), + __A, + __C); +} + +#else +#define _mm512_cvtt_roundph_epu16(A, B) \ + ((__m512i) \ + __builtin_ia32_vcvttph2uw512_mask_round ((A), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (__mmask32)-1, \ + (B))) + +#define _mm512_mask_cvtt_roundph_epu16(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vcvttph2uw512_mask_round ((C), \ + (__v32hi)(A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvtt_roundph_epu16(A, B, C) \ + ((__m512i) \ + __builtin_ia32_vcvttph2uw512_mask_round ((B), \ + (__v32hi) \ + _mm512_setzero_si512 (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtw2ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtepi16_ph (__m512i __A) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __A, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepi16_ph (__m512h __A, __mmask32 __B, __m512i __C) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepi16_ph (__mmask32 __A, __m512i __B) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __B, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepi16_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __A, + _mm512_setzero_ph (), + (__mmask32) -1, + __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepi16_ph (__m512h __A, __mmask32 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __C, + __A, + __B, + __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepi16_ph (__mmask32 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __B, + _mm512_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepi16_ph(A, B) \ + (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(A), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, \ + (B))) + +#define _mm512_mask_cvt_roundepi16_ph(A, B, C, D) \ + (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(C), \ + (A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvt_roundepi16_ph(A, B, C) \ + (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(B), \ + _mm512_setzero_ph (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtuw2ph. */ + extern __inline __m512h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) + _mm512_cvtepu16_ph (__m512i __A) + { + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __A, + _mm512_setzero_ph (), + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); + } + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtepu16_ph (__m512h __A, __mmask32 __B, __m512i __C) +{ + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __C, + __A, + __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtepu16_ph (__mmask32 __A, __m512i __B) +{ + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __B, + _mm512_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundepu16_ph (__m512i __A, int __B) +{ + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __A, + _mm512_setzero_ph (), + (__mmask32) -1, + __B); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundepu16_ph (__m512h __A, __mmask32 __B, __m512i __C, int __D) +{ + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __C, + __A, + __B, + __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundepu16_ph (__mmask32 __A, __m512i __B, int __C) +{ + return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __B, + _mm512_setzero_ph (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundepu16_ph(A, B) \ + (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(A), \ + _mm512_setzero_ph (), \ + (__mmask32)-1, \ + (B))) + +#define _mm512_mask_cvt_roundepu16_ph(A, B, C, D) \ + (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(C), \ + (A), \ + (B), \ + (D))) + +#define _mm512_maskz_cvt_roundepu16_ph(A, B, C) \ + (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(B), \ + _mm512_setzero_ph (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2pd. */ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtph_pd (__m128h __A) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__A, + _mm512_setzero_pd (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtph_pd (__m512d __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtph_pd (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__B, + _mm512_setzero_pd (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundph_pd (__m128h __A, int __B) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__A, + _mm512_setzero_pd (), + (__mmask8) -1, + __B); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundph_pd (__m512d __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundph_pd (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_vcvtph2pd512_mask_round (__B, + _mm512_setzero_pd (), + __A, + __C); +} + +#else +#define _mm512_cvt_roundph_pd(A, B) \ + (__builtin_ia32_vcvtph2pd512_mask_round ((A), \ + _mm512_setzero_pd (), \ + (__mmask8)-1, \ + (B))) + +#define _mm512_mask_cvt_roundph_pd(A, B, C, D) \ + (__builtin_ia32_vcvtph2pd512_mask_round ((C), (A), (B), (D))) + +#define _mm512_maskz_cvt_roundph_pd(A, B, C) \ + (__builtin_ia32_vcvtph2pd512_mask_round ((B), \ + _mm512_setzero_pd (), \ + (A), \ + (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2psx. */ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtxph_ps (__m256h __A) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__A, + _mm512_setzero_ps (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtxph_ps (__m512 __A, __mmask16 __B, __m256h __C) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__C, __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtxph_ps (__mmask16 __A, __m256h __B) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__B, + _mm512_setzero_ps (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtx_roundph_ps (__m256h __A, int __B) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__A, + _mm512_setzero_ps (), + (__mmask16) -1, + __B); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtx_roundph_ps (__m512 __A, __mmask16 __B, __m256h __C, int __D) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__C, __A, __B, __D); +} + +extern __inline __m512 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtx_roundph_ps (__mmask16 __A, __m256h __B, int __C) +{ + return __builtin_ia32_vcvtph2psx512_mask_round (__B, + _mm512_setzero_ps (), + __A, + __C); +} + +#else +#define _mm512_cvtx_roundph_ps(A, B) \ + (__builtin_ia32_vcvtph2psx512_mask_round ((A), \ + _mm512_setzero_ps (), \ + (__mmask16)-1, \ + (B))) + +#define _mm512_mask_cvtx_roundph_ps(A, B, C, D) \ + (__builtin_ia32_vcvtph2psx512_mask_round ((C), (A), (B), (D))) + +#define _mm512_maskz_cvtx_roundph_ps(A, B, C) \ + (__builtin_ia32_vcvtph2psx512_mask_round ((B), \ + _mm512_setzero_ps (), \ + (A), \ + (C))) +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtps2ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtxps_ph (__m512 __A) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtxps_ph (__m256h __A, __mmask16 __B, __m512 __C) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __C, + __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtxps_ph (__mmask16 __A, __m512 __B) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __B, + _mm256_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtx_roundps_ph (__m512 __A, int __B) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __A, + _mm256_setzero_ph (), + (__mmask16) -1, + __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtx_roundps_ph (__m256h __A, __mmask16 __B, __m512 __C, int __D) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __C, + __A, __B, __D); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtx_roundps_ph (__mmask16 __A, __m512 __B, int __C) +{ + return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __B, + _mm256_setzero_ph (), + __A, __C); +} + +#else +#define _mm512_cvtx_roundps_ph(A, B) \ + (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(A), \ + _mm256_setzero_ph (),\ + (__mmask16)-1, (B))) + +#define _mm512_mask_cvtx_roundps_ph(A, B, C, D) \ + (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(C), \ + (A), (B), (D))) + +#define _mm512_maskz_cvtx_roundps_ph(A, B, C) \ + (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(B), \ + _mm256_setzero_ph (),\ + (A), (C))) +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtpd2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvtpd_ph (__m512d __A) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __A, + _mm_setzero_ph (), + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m512d __C) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __C, + __A, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvtpd_ph (__mmask8 __A, __m512d __B) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __B, + _mm_setzero_ph (), + __A, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_cvt_roundpd_ph (__m512d __A, int __B) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __A, + _mm_setzero_ph (), + (__mmask8) -1, + __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_cvt_roundpd_ph (__m128h __A, __mmask8 __B, __m512d __C, int __D) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __C, + __A, __B, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_cvt_roundpd_ph (__mmask8 __A, __m512d __B, int __C) +{ + return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __B, + _mm_setzero_ph (), + __A, __C); +} + +#else +#define _mm512_cvt_roundpd_ph(A, B) \ + (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(A), \ + _mm_setzero_ph (), \ + (__mmask8)-1, (B))) + +#define _mm512_mask_cvt_roundpd_ph(A, B, C, D) \ + (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(C), \ + (A), (B), (D))) + +#define _mm512_maskz_cvt_roundpd_ph(A, B, C) \ + (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(B), \ + _mm_setzero_ph (), \ + (A), (C))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfmaddsub[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmaddsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmaddsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmaddsub_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmaddsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmaddsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fmaddsub_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddsubph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fmaddsub_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddsubph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fmaddsub_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfmaddsubph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fmaddsub_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddsubph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfmsubadd[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) + _mm512_fmsubadd_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_ph (__m512h __A, __mmask32 __U, + __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_ph (__m512h __A, __m512h __B, + __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_ph (__mmask32 __U, __m512h __A, + __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsubadd_round_ph (__m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsubadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsubadd_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsubadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) + __builtin_ia32_vfmsubaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fmsubadd_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubaddph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fmsubadd_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubaddph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fmsubadd_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfmsubaddph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fmsubadd_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubaddph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfmadd[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) + _mm512_fmadd_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfmaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) __builtin_ia32_vfmaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fmadd_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fmadd_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fmadd_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfmaddph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fmadd_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmaddph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfnmadd[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfnmaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmaddph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmaddph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fnmadd_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmaddph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fnmadd_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmaddph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fnmadd_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfnmaddph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fnmadd_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmaddph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfmsub[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfmsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) __builtin_ia32_vfmsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfmsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fmsub_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fmsub_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fmsub_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfmsubph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fmsub_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfmsubph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfnmsub[132,213,231]ph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_ph (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U) +{ + return (__m512h) + __builtin_ia32_vfnmsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfnmsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, + _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fnmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) -1, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fnmsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fnmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, + __mmask32 __U, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmsubph512_mask3 ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fnmsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B, + __m512h __C, const int __R) +{ + return (__m512h) __builtin_ia32_vfnmsubph512_maskz ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + (__mmask32) __U, __R); +} + +#else +#define _mm512_fnmsub_round_ph(A, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmsubph512_mask ((A), (B), (C), -1, (R))) + +#define _mm512_mask_fnmsub_round_ph(A, U, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmsubph512_mask ((A), (B), (C), (U), (R))) + +#define _mm512_mask3_fnmsub_round_ph(A, B, C, U, R) \ + ((__m512h)__builtin_ia32_vfnmsubph512_mask3 ((A), (B), (C), (U), (R))) + +#define _mm512_maskz_fnmsub_round_ph(U, A, B, C, R) \ + ((__m512h)__builtin_ia32_vfnmsubph512_maskz ((A), (B), (C), (U), (R))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vf[,c]maddcph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fcmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A, + (__v32hf) __C, + (__v32hf) __D, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_mask3_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fcmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B, + (__v32hf) __C, + (__v32hf) __D, + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_pch (__m512h __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A, + (__v32hf) __C, + (__v32hf) __D, __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_mask3_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B, + (__v32hf) __C, + (__v32hf) __D, + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fcmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A, + (__v32hf) __C, + (__v32hf) __D, __B, + __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, + __mmask16 __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_mask3_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fcmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B, + (__v32hf) __C, + (__v32hf) __D, + __A, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A, + (__v32hf) __C, + (__v32hf) __D, __B, + __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask3_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, + __mmask16 __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_mask3_round ((__v32hf) __A, + (__v32hf) __B, + (__v32hf) __C, + __D, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B, + (__v32hf) __C, + (__v32hf) __D, + __A, __E); +} + +#else +#define _mm512_fcmadd_round_pch(A, B, C, D) \ + (__m512h) __builtin_ia32_vfcmaddcph512_round ((A), (B), (C), (D)) + +#define _mm512_mask_fcmadd_round_pch(A, B, C, D, E) \ + ((__m512h) \ + __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) (A), \ + (__v32hf) (C), \ + (__v32hf) (D), \ + (B), (E))) + + +#define _mm512_mask3_fcmadd_round_pch(A, B, C, D, E) \ + ((__m512h) \ + __builtin_ia32_vfcmaddcph512_mask3_round ((A), (B), (C), (D), (E))) + +#define _mm512_maskz_fcmadd_round_pch(A, B, C, D, E) \ + (__m512h) \ + __builtin_ia32_vfcmaddcph512_maskz_round ((B), (C), (D), (A), (E)) + +#define _mm512_fmadd_round_pch(A, B, C, D) \ + (__m512h) __builtin_ia32_vfmaddcph512_round ((A), (B), (C), (D)) + +#define _mm512_mask_fmadd_round_pch(A, B, C, D, E) \ + ((__m512h) \ + __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) (A), \ + (__v32hf) (C), \ + (__v32hf) (D), \ + (B), (E))) + +#define _mm512_mask3_fmadd_round_pch(A, B, C, D, E) \ + (__m512h) \ + __builtin_ia32_vfmaddcph512_mask3_round ((A), (B), (C), (D), (E)) + +#define _mm512_maskz_fmadd_round_pch(A, B, C, D, E) \ + (__m512h) \ + __builtin_ia32_vfmaddcph512_maskz_round ((B), (C), (D), (A), (E)) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vf[,c]mulcph. */ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fcmul_pch (__m512h __A, __m512h __B) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_round ((__v32hf) __A, + (__v32hf) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fcmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C, + (__v32hf) __D, + (__v32hf) __A, + __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fcmul_pch (__mmask16 __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B, + (__v32hf) __C, + _mm512_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmul_pch (__m512h __A, __m512h __B) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_round ((__v32hf) __A, + (__v32hf) __B, + _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C, + (__v32hf) __D, + (__v32hf) __A, + __B, _MM_FROUND_CUR_DIRECTION); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmul_pch (__mmask16 __A, __m512h __B, __m512h __C) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B, + (__v32hf) __C, + _mm512_setzero_ph (), + __A, _MM_FROUND_CUR_DIRECTION); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fcmul_round_pch (__m512h __A, __m512h __B, const int __D) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_round ((__v32hf) __A, + (__v32hf) __B, __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fcmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C, + (__v32hf) __D, + (__v32hf) __A, + __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fcmul_round_pch (__mmask16 __A, __m512h __B, + __m512h __C, const int __E) +{ + return (__m512h) + __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B, + (__v32hf) __C, + _mm512_setzero_ph (), + __A, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_fmul_round_pch (__m512h __A, __m512h __B, const int __D) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_round ((__v32hf) __A, + (__v32hf) __B, + __D); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_fmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C, + __m512h __D, const int __E) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C, + (__v32hf) __D, + (__v32hf) __A, + __B, __E); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_fmul_round_pch (__mmask16 __A, __m512h __B, + __m512h __C, const int __E) +{ + return (__m512h) + __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B, + (__v32hf) __C, + _mm512_setzero_ph (), + __A, __E); +} + +#else +#define _mm512_fcmul_round_pch(A, B, D) \ + (__m512h) __builtin_ia32_vfcmulcph512_round ((A), (B), (D)) + +#define _mm512_mask_fcmul_round_pch(A, B, C, D, E) \ + (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((C), (D), (A), (B), (E)) + +#define _mm512_maskz_fcmul_round_pch(A, B, C, E) \ + (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((B), (C), \ + (__v32hf) \ + _mm512_setzero_ph (), \ + (A), (E)) + +#define _mm512_fmul_round_pch(A, B, D) \ + (__m512h) __builtin_ia32_vfmulcph512_round ((A), (B), (D)) + +#define _mm512_mask_fmul_round_pch(A, B, C, D, E) \ + (__m512h) __builtin_ia32_vfmulcph512_mask_round ((C), (D), (A), (B), (E)) + +#define _mm512_maskz_fmul_round_pch(A, B, C, E) \ + (__m512h) __builtin_ia32_vfmulcph512_mask_round ((B), (C), \ + (__v32hf) \ + _mm512_setzero_ph (), \ + (A), (E)) + +#endif /* __OPTIMIZE__ */ + +#define _MM512_REDUCE_OP(op) \ + __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \ + __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \ + __m256h __T3 = (__T1 op __T2); \ + __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \ + __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \ + __m128h __T6 = (__T4 op __T5); \ + __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \ + (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \ + __m128h __T8 = (__T6 op __T7); \ + __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \ + (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \ + __m128h __T10 = __T8 op __T9; \ + return __T10[0] op __T10[1] + +// TODO reduce +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_add_ph (__m512h __A) +{ + _MM512_REDUCE_OP (+); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_mul_ph (__m512h __A) +{ + _MM512_REDUCE_OP (*); +} + +#undef _MM512_REDUCE_OP + +#ifdef __AVX512VL__ + +#define _MM512_REDUCE_OP(op) \ + __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \ + __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \ + __m256h __T3 = __builtin_ia32_##op##ph256_mask (__T1, __T2, \ + _mm256_setzero_ph (), (__mmask16) -1); \ + __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \ + __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \ + __m128h __T6 = __builtin_ia32_##op##ph128_mask \ + (__T4, __T5, _mm_setzero_ph (),(__mmask8) -1); \ + __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \ + (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \ + __m128h __T8 = (__m128h) __builtin_ia32_##op##ph128_mask \ + (__T6, __T7, _mm_setzero_ph (),(__mmask8) -1); \ + __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \ + (__v8hi) { 4, 5 }); \ + __m128h __T10 = __builtin_ia32_##op##ph128_mask \ + (__T8, __T9, _mm_setzero_ph (),(__mmask8) -1); \ + __m128h __T11 = (__m128h) __builtin_shuffle (__T10, \ + (__v8hi) { 1, 0 }); \ + __m128h __T12 = __builtin_ia32_##op##ph128_mask \ + (__T10, __T11, _mm_setzero_ph (),(__mmask8) -1); \ + return __T12[0] + +#else + +#define _MM512_REDUCE_OP(op) \ + __m512h __T1 = (__m512h) __builtin_shuffle ((__m512d) __A, \ + (__v8di) { 4, 5, 6, 7, 0, 0, 0, 0 }); \ + __m512h __T2 = _mm512_##op##_ph (__A, __T1); \ + __m512h __T3 = (__m512h) __builtin_shuffle ((__m512d) __T2, \ + (__v8di) { 2, 3, 0, 0, 0, 0, 0, 0 }); \ + __m512h __T4 = _mm512_##op##_ph (__T2, __T3); \ + __m512h __T5 = (__m512h) __builtin_shuffle ((__m512d) __T4, \ + (__v8di) { 1, 0, 0, 0, 0, 0, 0, 0 }); \ + __m512h __T6 = _mm512_##op##_ph (__T4, __T5); \ + __m512h __T7 = (__m512h) __builtin_shuffle ((__m512) __T6, \ + (__v16si) { 1, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0 }); \ + __m512h __T8 = _mm512_##op##_ph (__T6, __T7); \ + __m512h __T9 = (__m512h) __builtin_shuffle (__T8, \ + (__v32hi) { 1, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0 }); \ + __m512h __T10 = _mm512_##op##_ph (__T8, __T9); \ + return __T10[0] +#endif + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_min_ph (__m512h __A) +{ + _MM512_REDUCE_OP (min); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_reduce_max_ph (__m512h __A) +{ + _MM512_REDUCE_OP (max); +} + +#undef _MM512_REDUCE_OP + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_blend_ph (__mmask32 __U, __m512h __A, __m512h __W) +{ + return (__m512h) __builtin_ia32_movdquhi512_mask ((__v32hi) __W, + (__v32hi) __A, + (__mmask32) __U); + +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_ph (__m512h __A, __m512i __I, __m512h __B) +{ + return (__m512h) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A, + (__v32hi) __I, + (__v32hi) __B, + (__mmask32)-1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_ph (__m512i __A, __m512h __B) +{ + return (__m512h) __builtin_ia32_permvarhi512_mask ((__v32hi) __B, + (__v32hi) __A, + (__v32hi) + (_mm512_setzero_ph ()), + (__mmask32)-1); +} + +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex __a; + float __b; + } __u = { .__a = __A}; + + return (__m512h) _mm512_set1_ps (__u.__b); +} + +// intrinsics below are alias for f*mul_*ch +#define _mm512_mul_pch(A, B) _mm512_fmul_pch ((A), (B)) +#define _mm512_mask_mul_pch(W, U, A, B) \ + _mm512_mask_fmul_pch ((W), (U), (A), (B)) +#define _mm512_maskz_mul_pch(U, A, B) _mm512_maskz_fmul_pch ((U), (A), (B)) +#define _mm512_mul_round_pch(A, B, R) _mm512_fmul_round_pch ((A), (B), (R)) +#define _mm512_mask_mul_round_pch(W, U, A, B, R) \ + _mm512_mask_fmul_round_pch ((W), (U), (A), (B), (R)) +#define _mm512_maskz_mul_round_pch(U, A, B, R) \ + _mm512_maskz_fmul_round_pch ((U), (A), (B), (R)) + +#define _mm512_cmul_pch(A, B) _mm512_fcmul_pch ((A), (B)) +#define _mm512_mask_cmul_pch(W, U, A, B) \ + _mm512_mask_fcmul_pch ((W), (U), (A), (B)) +#define _mm512_maskz_cmul_pch(U, A, B) _mm512_maskz_fcmul_pch ((U), (A), (B)) +#define _mm512_cmul_round_pch(A, B, R) _mm512_fcmul_round_pch ((A), (B), (R)) +#define _mm512_mask_cmul_round_pch(W, U, A, B, R) \ + _mm512_mask_fcmul_round_pch ((W), (U), (A), (B), (R)) +#define _mm512_maskz_cmul_round_pch(U, A, B, R) \ + _mm512_maskz_fcmul_round_pch ((U), (A), (B), (R)) + +#ifdef __DISABLE_AVX512FP16_512__ +#undef __DISABLE_AVX512FP16_512__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512FP16_512__ */ + +#endif /* _AVX512FP16INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512fp16vlintrin.h b/template/sysroot/include/avx512fp16vlintrin.h new file mode 100644 index 0000000..a1e1cb5 --- /dev/null +++ b/template/sysroot/include/avx512fp16vlintrin.h @@ -0,0 +1,3388 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef __AVX512FP16VLINTRIN_H_INCLUDED +#define __AVX512FP16VLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512FP16__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512fp16,avx512vl,no-evex512") +#define __DISABLE_AVX512FP16VL__ +#endif /* __AVX512FP16VL__ */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set1_ps (float __F) +{ + return __extension__ (__m128)(__v4sf){ __F, __F, __F, __F }; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set1_ps (float __A) +{ + return __extension__ (__m256){ __A, __A, __A, __A, + __A, __A, __A, __A }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_and_si128 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A & (__v2du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_and_si256 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A & (__v4du)__B); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castph_ps (__m128h __a) +{ + return (__m128) __a; +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castph_ps (__m256h __a) +{ + return (__m256) __a; +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castph_pd (__m128h __a) +{ + return (__m128d) __a; +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castph_pd (__m256h __a) +{ + return (__m256d) __a; +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castph_si128 (__m128h __a) +{ + return (__m128i) __a; +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castph_si256 (__m256h __a) +{ + return (__m256i) __a; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castps_ph (__m128 __a) +{ + return (__m128h) __a; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castps_ph (__m256 __a) +{ + return (__m256h) __a; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castpd_ph (__m128d __a) +{ + return (__m128h) __a; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castpd_ph (__m256d __a) +{ + return (__m256h) __a; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castsi128_ph (__m128i __a) +{ + return (__m128h) __a; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castsi256_ph (__m256i __a) +{ + return (__m256h) __a; +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castph256_ph128 (__m256h __A) +{ + union + { + __m128h __a[2]; + __m256h __v; + } __u = { .__v = __A }; + return __u.__a[0]; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castph128_ph256 (__m128h __A) +{ + union + { + __m128h __a[2]; + __m256h __v; + } __u; + __u.__a[0] = __A; + return __u.__v; +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zextph128_ph256 (__m128h __A) +{ + return (__m256h) _mm256_avx512_insertf128_ps (_mm256_avx512_setzero_ps (), + (__m128) __A, 0); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_conj_pch (__m256h __A) +{ + return (__m256h) _mm256_xor_epi32 ((__m256i) __A, _mm256_avx512_set1_epi32 (1<<31)); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_conj_pch (__m256h __W, __mmask8 __U, __m256h __A) +{ + return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf) + _mm256_conj_pch (__A), + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_conj_pch (__mmask8 __U, __m256h __A) +{ + return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf) + _mm256_conj_pch (__A), + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_conj_pch (__m128h __A) +{ + return (__m128h) _mm_xor_epi32 ((__m128i) __A, _mm_avx512_set1_epi32 (1<<31)); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_conj_pch (__m128h __W, __mmask8 __U, __m128h __A) +{ + return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A), + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_conj_pch (__mmask8 __U, __m128h __A) +{ + return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A), + (__v4sf) _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +/* Intrinsics v[add,sub,mul,div]ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_ph (__m128h __A, __m128h __B) +{ + return (__m128h) ((__v8hf) __A + (__v8hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_ph (__m256h __A, __m256h __B) +{ + return (__m256h) ((__v16hf) __A + (__v16hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_addph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_addph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_addph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_addph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_ph (__m128h __A, __m128h __B) +{ + return (__m128h) ((__v8hf) __A - (__v8hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_ph (__m256h __A, __m256h __B) +{ + return (__m256h) ((__v16hf) __A - (__v16hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_subph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_subph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_subph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_subph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_ph (__m128h __A, __m128h __B) +{ + return (__m128h) ((__v8hf) __A * (__v8hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mul_ph (__m256h __A, __m256h __B) +{ + return (__m256h) ((__v16hf) __A * (__v16hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_mulph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mul_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_mulph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_mulph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mul_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_mulph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_ph (__m128h __A, __m128h __B) +{ + return (__m128h) ((__v8hf) __A / (__v8hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_div_ph (__m256h __A, __m256h __B) +{ + return (__m256h) ((__v16hf) __A / (__v16hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_divph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_div_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_divph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_divph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_div_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_divph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +/* Intrinsics v[max,min]ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_ph (__m128h __A, __m128h __B) +{ + return __builtin_ia32_maxph128_mask (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_ph (__m256h __A, __m256h __B) +{ + return __builtin_ia32_maxph256_mask (__A, __B, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_maxph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_maxph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_maxph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_maxph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_ph (__m128h __A, __m128h __B) +{ + return __builtin_ia32_minph128_mask (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_ph (__m256h __A, __m256h __B) +{ + return __builtin_ia32_minph256_mask (__A, __B, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_minph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D) +{ + return __builtin_ia32_minph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_minph128_mask (__B, __C, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_minph256_mask (__B, __C, + _mm256_setzero_ph (), __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_ph (__m128h __A) +{ + return (__m128h) _mm_avx512_and_si128 (_mm_avx512_set1_epi32 (0x7FFF7FFF), + (__m128i) __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_abs_ph (__m256h __A) +{ + return (__m256h) _mm256_avx512_and_si256 (_mm256_avx512_set1_epi32 (0x7FFF7FFF), + (__m256i) __A); +} + +/* vcmpph */ +#ifdef __OPTIMIZE +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ph_mask (__m128h __A, __m128h __B, const int __C) +{ + return (__mmask8) __builtin_ia32_cmpph128_mask (__A, __B, __C, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_ph_mask (__mmask8 __A, __m128h __B, __m128h __C, + const int __D) +{ + return (__mmask8) __builtin_ia32_cmpph128_mask (__B, __C, __D, __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ph_mask (__m256h __A, __m256h __B, const int __C) +{ + return (__mmask16) __builtin_ia32_cmpph256_mask (__A, __B, __C, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_ph_mask (__mmask16 __A, __m256h __B, __m256h __C, + const int __D) +{ + return (__mmask16) __builtin_ia32_cmpph256_mask (__B, __C, __D, + __A); +} + +#else +#define _mm_cmp_ph_mask(A, B, C) \ + (__builtin_ia32_cmpph128_mask ((A), (B), (C), (-1))) + +#define _mm_mask_cmp_ph_mask(A, B, C, D) \ + (__builtin_ia32_cmpph128_mask ((B), (C), (D), (A))) + +#define _mm256_cmp_ph_mask(A, B, C) \ + (__builtin_ia32_cmpph256_mask ((A), (B), (C), (-1))) + +#define _mm256_mask_cmp_ph_mask(A, B, C, D) \ + (__builtin_ia32_cmpph256_mask ((B), (C), (D), (A))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vsqrtph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_ph (__m128h __A) +{ + return __builtin_ia32_sqrtph128_mask (__A, _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sqrt_ph (__m256h __A) +{ + return __builtin_ia32_sqrtph256_mask (__A, _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_ph (__m128h __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_sqrtph128_mask (__C, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sqrt_ph (__m256h __A, __mmask16 __B, __m256h __C) +{ + return __builtin_ia32_sqrtph256_mask (__C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_ph (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_sqrtph128_mask (__B, _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sqrt_ph (__mmask16 __A, __m256h __B) +{ + return __builtin_ia32_sqrtph256_mask (__B, _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vrsqrtph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt_ph (__m128h __A) +{ + return __builtin_ia32_rsqrtph128_mask (__A, _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rsqrt_ph (__m256h __A) +{ + return __builtin_ia32_rsqrtph256_mask (__A, _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt_ph (__m128h __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_rsqrtph128_mask (__C, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rsqrt_ph (__m256h __A, __mmask16 __B, __m256h __C) +{ + return __builtin_ia32_rsqrtph256_mask (__C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt_ph (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_rsqrtph128_mask (__B, _mm_setzero_ph (), __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rsqrt_ph (__mmask16 __A, __m256h __B) +{ + return __builtin_ia32_rsqrtph256_mask (__B, _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vrcpph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp_ph (__m128h __A) +{ + return __builtin_ia32_rcpph128_mask (__A, _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rcp_ph (__m256h __A) +{ + return __builtin_ia32_rcpph256_mask (__A, _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp_ph (__m128h __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_rcpph128_mask (__C, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rcp_ph (__m256h __A, __mmask16 __B, __m256h __C) +{ + return __builtin_ia32_rcpph256_mask (__C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp_ph (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_rcpph128_mask (__B, _mm_setzero_ph (), __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rcp_ph (__mmask16 __A, __m256h __B) +{ + return __builtin_ia32_rcpph256_mask (__B, _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vscalefph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_ph (__m128h __A, __m128h __B) +{ + return __builtin_ia32_scalefph128_mask (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_scalef_ph (__m256h __A, __m256h __B) +{ + return __builtin_ia32_scalefph256_mask (__A, __B, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return __builtin_ia32_scalefph128_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_scalef_ph (__m256h __A, __mmask16 __B, __m256h __C, + __m256h __D) +{ + return __builtin_ia32_scalefph256_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_ph (__mmask8 __A, __m128h __B, __m128h __C) +{ + return __builtin_ia32_scalefph128_mask (__B, __C, + _mm_setzero_ph (), __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_scalef_ph (__mmask16 __A, __m256h __B, __m256h __C) +{ + return __builtin_ia32_scalefph256_mask (__B, __C, + _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vreduceph. */ +#ifdef __OPTIMIZE__ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_ph (__m128h __A, int __B) +{ + return __builtin_ia32_reduceph128_mask (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_ph (__m128h __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_reduceph128_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_ph (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_reduceph128_mask (__B, __C, + _mm_setzero_ph (), __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_ph (__m256h __A, int __B) +{ + return __builtin_ia32_reduceph256_mask (__A, __B, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_ph (__m256h __A, __mmask16 __B, __m256h __C, int __D) +{ + return __builtin_ia32_reduceph256_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_reduce_ph (__mmask16 __A, __m256h __B, int __C) +{ + return __builtin_ia32_reduceph256_mask (__B, __C, + _mm256_setzero_ph (), + __A); +} + +#else +#define _mm_reduce_ph(A, B) \ + (__builtin_ia32_reduceph128_mask ((A), (B), \ + _mm_setzero_ph (), \ + ((__mmask8)-1))) + +#define _mm_mask_reduce_ph(A, B, C, D) \ + (__builtin_ia32_reduceph128_mask ((C), (D), (A), (B))) + +#define _mm_maskz_reduce_ph(A, B, C) \ + (__builtin_ia32_reduceph128_mask ((B), (C), _mm_setzero_ph (), (A))) + +#define _mm256_reduce_ph(A, B) \ + (__builtin_ia32_reduceph256_mask ((A), (B), \ + _mm256_setzero_ph (), \ + ((__mmask16)-1))) + +#define _mm256_mask_reduce_ph(A, B, C, D) \ + (__builtin_ia32_reduceph256_mask ((C), (D), (A), (B))) + +#define _mm256_maskz_reduce_ph(A, B, C) \ + (__builtin_ia32_reduceph256_mask ((B), (C), _mm256_setzero_ph (), (A))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vrndscaleph. */ +#ifdef __OPTIMIZE__ + extern __inline __m128h + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) + _mm_roundscale_ph (__m128h __A, int __B) + { + return __builtin_ia32_rndscaleph128_mask (__A, __B, + _mm_setzero_ph (), + (__mmask8) -1); + } + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_ph (__m128h __A, __mmask8 __B, __m128h __C, int __D) +{ + return __builtin_ia32_rndscaleph128_mask (__C, __D, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_ph (__mmask8 __A, __m128h __B, int __C) +{ + return __builtin_ia32_rndscaleph128_mask (__B, __C, + _mm_setzero_ph (), __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_roundscale_ph (__m256h __A, int __B) +{ + return __builtin_ia32_rndscaleph256_mask (__A, __B, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_roundscale_ph (__m256h __A, __mmask16 __B, __m256h __C, + int __D) +{ + return __builtin_ia32_rndscaleph256_mask (__C, __D, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_roundscale_ph (__mmask16 __A, __m256h __B, int __C) +{ + return __builtin_ia32_rndscaleph256_mask (__B, __C, + _mm256_setzero_ph (), + __A); +} + +#else +#define _mm_roundscale_ph(A, B) \ + (__builtin_ia32_rndscaleph128_mask ((A), (B), _mm_setzero_ph (), \ + ((__mmask8)-1))) + +#define _mm_mask_roundscale_ph(A, B, C, D) \ + (__builtin_ia32_rndscaleph128_mask ((C), (D), (A), (B))) + +#define _mm_maskz_roundscale_ph(A, B, C) \ + (__builtin_ia32_rndscaleph128_mask ((B), (C), _mm_setzero_ph (), (A))) + +#define _mm256_roundscale_ph(A, B) \ + (__builtin_ia32_rndscaleph256_mask ((A), (B), \ + _mm256_setzero_ph(), \ + ((__mmask16)-1))) + +#define _mm256_mask_roundscale_ph(A, B, C, D) \ + (__builtin_ia32_rndscaleph256_mask ((C), (D), (A), (B))) + +#define _mm256_maskz_roundscale_ph(A, B, C) \ + (__builtin_ia32_rndscaleph256_mask ((B), (C), \ + _mm256_setzero_ph (), (A))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vfpclassph. */ +#ifdef __OPTIMIZE__ +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) + _mm_mask_fpclass_ph_mask (__mmask8 __U, __m128h __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_ph_mask (__m128h __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fpclass_ph_mask (__mmask16 __U, __m256h __A, const int __imm) +{ + return (__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) __A, + __imm, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fpclass_ph_mask (__m256h __A, const int __imm) +{ + return (__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) __A, + __imm, + (__mmask16) -1); +} + +#else +#define _mm_fpclass_ph_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) (__m128h) (X), \ + (int) (C),(__mmask8)-1)) + +#define _mm_mask_fpclass_ph_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) (__m128h) (X), \ + (int) (C),(__mmask8)(u))) + +#define _mm256_fpclass_ph_mask(X, C) \ + ((__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) (__m256h) (X), \ + (int) (C),(__mmask16)-1)) + +#define _mm256_mask_fpclass_ph_mask(u, X, C) \ + ((__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) (__m256h) (X), \ + (int) (C),(__mmask16)(u))) +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vgetexpph, vgetexpsh. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getexp_ph (__m256h __A) +{ + return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A, + (__v16hf) + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getexp_ph (__m256h __W, __mmask16 __U, __m256h __A) +{ + return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A, + (__v16hf) __W, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getexp_ph (__mmask16 __U, __m256h __A) +{ + return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A, + (__v16hf) + _mm256_setzero_ph (), + (__mmask16) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_ph (__m128h __A) +{ + return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A, + (__v8hf) + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_ph (__m128h __W, __mmask8 __U, __m128h __A) +{ + return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A, + (__v8hf) __W, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_ph (__mmask8 __U, __m128h __A) +{ + return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A, + (__v8hf) + _mm_setzero_ph (), + (__mmask8) __U); +} + + +/* Intrinsics vgetmantph, vgetmantsh. */ +#ifdef __OPTIMIZE__ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getmant_ph (__m256h __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A, + (__C << 2) | __B, + (__v16hf) + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getmant_ph (__m256h __W, __mmask16 __U, __m256h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A, + (__C << 2) | __B, + (__v16hf) __W, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getmant_ph (__mmask16 __U, __m256h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A, + (__C << 2) | __B, + (__v16hf) + _mm256_setzero_ph (), + (__mmask16) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_ph (__m128h __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A, + (__C << 2) | __B, + (__v8hf) + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_ph (__m128h __W, __mmask8 __U, __m128h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A, + (__C << 2) | __B, + (__v8hf) __W, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_ph (__mmask8 __U, __m128h __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A, + (__C << 2) | __B, + (__v8hf) + _mm_setzero_ph (), + (__mmask8) __U); +} + +#else +#define _mm256_getmant_ph(X, B, C) \ + ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v16hf)(__m256h)_mm256_setzero_ph (), \ + (__mmask16)-1)) + +#define _mm256_mask_getmant_ph(W, U, X, B, C) \ + ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v16hf)(__m256h)(W), \ + (__mmask16)(U))) + +#define _mm256_maskz_getmant_ph(U, X, B, C) \ + ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v16hf)(__m256h)_mm256_setzero_ph (), \ + (__mmask16)(U))) + +#define _mm_getmant_ph(X, B, C) \ + ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8hf)(__m128h)_mm_setzero_ph (), \ + (__mmask8)-1)) + +#define _mm_mask_getmant_ph(W, U, X, B, C) \ + ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8hf)(__m128h)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_getmant_ph(U, X, B, C) \ + ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8hf)(__m128h)_mm_setzero_ph (), \ + (__mmask8)(U))) + +#endif /* __OPTIMIZE__ */ + +/* Intrinsics vcvtph2dq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epi32 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvtph2dq128_mask (__A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epi32 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvtph2dq128_mask (__C, ( __v4si) __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epi32 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvtph2dq128_mask (__B, + (__v4si) _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epi32 (__m128h __A) +{ + return (__m256i) + __builtin_ia32_vcvtph2dq256_mask (__A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epi32 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return (__m256i) + __builtin_ia32_vcvtph2dq256_mask (__C, ( __v8si) __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epi32 (__mmask8 __A, __m128h __B) +{ + return (__m256i) + __builtin_ia32_vcvtph2dq256_mask (__B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtph2udq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epu32 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvtph2udq128_mask (__A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epu32 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvtph2udq128_mask (__C, ( __v4si) __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epu32 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvtph2udq128_mask (__B, + (__v4si) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epu32 (__m128h __A) +{ + return (__m256i) + __builtin_ia32_vcvtph2udq256_mask (__A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epu32 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return (__m256i) + __builtin_ia32_vcvtph2udq256_mask (__C, ( __v8si) __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epu32 (__mmask8 __A, __m128h __B) +{ + return (__m256i) + __builtin_ia32_vcvtph2udq256_mask (__B, + (__v8si) _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2dq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epi32 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvttph2dq128_mask (__A, + (__v4si) _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epi32 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i)__builtin_ia32_vcvttph2dq128_mask (__C, + ( __v4si) __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epi32 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvttph2dq128_mask (__B, + (__v4si) _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epi32 (__m128h __A) +{ + return (__m256i) + __builtin_ia32_vcvttph2dq256_mask (__A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epi32 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return (__m256i) + __builtin_ia32_vcvttph2dq256_mask (__C, + ( __v8si) __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epi32 (__mmask8 __A, __m128h __B) +{ + return (__m256i) + __builtin_ia32_vcvttph2dq256_mask (__B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2udq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epu32 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvttph2udq128_mask (__A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epu32 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvttph2udq128_mask (__C, + ( __v4si) __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epu32 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvttph2udq128_mask (__B, + (__v4si) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epu32 (__m128h __A) +{ + return (__m256i) + __builtin_ia32_vcvttph2udq256_mask (__A, + (__v8si) + _mm256_avx512_setzero_si256 (), (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epu32 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return (__m256i) + __builtin_ia32_vcvttph2udq256_mask (__C, + ( __v8si) __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epu32 (__mmask8 __A, __m128h __B) +{ + return (__m256i) + __builtin_ia32_vcvttph2udq256_mask (__B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtdq2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_ph (__m128i __A) +{ + return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_ph (__m256i __A) +{ + return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_ph (__m128h __A, __mmask8 __B, __m256i __C) +{ + return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_ph (__mmask8 __A, __m256i __B) +{ + return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vcvtudq2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu32_ph (__m128i __A) +{ + return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu32_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __C, + __A, + __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu32_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu32_ph (__m256i __A) +{ + return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu32_ph (__m128h __A, __mmask8 __B, __m256i __C) +{ + return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu32_ph (__mmask8 __A, __m256i __B) +{ + return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vcvtph2qq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epi64 (__m128h __A) +{ + return + __builtin_ia32_vcvtph2qq128_mask (__A, + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epi64 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2qq128_mask (__C, __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2qq128_mask (__B, + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epi64 (__m128h __A) +{ + return __builtin_ia32_vcvtph2qq256_mask (__A, + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epi64 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2qq256_mask (__C, __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2qq256_mask (__B, + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtph2uqq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvtph2uqq128_mask (__A, + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epu64 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2uqq128_mask (__C, __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2uqq128_mask (__B, + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvtph2uqq256_mask (__A, + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epu64 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2uqq256_mask (__C, __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2uqq256_mask (__B, + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2qq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epi64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2qq128_mask (__A, + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epi64 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2qq128_mask (__C, + __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2qq128_mask (__B, + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epi64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2qq256_mask (__A, + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epi64 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2qq256_mask (__C, + __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2qq256_mask (__B, + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2uqq. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2uqq128_mask (__A, + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epu64 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2uqq128_mask (__C, + __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2uqq128_mask (__B, + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epu64 (__m128h __A) +{ + return __builtin_ia32_vcvttph2uqq256_mask (__A, + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epu64 (__m256i __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvttph2uqq256_mask (__C, + __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvttph2uqq256_mask (__B, + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtqq2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_ph (__m128i __A) +{ + return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_ph (__m256i __A) +{ + return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m256i __C) +{ + return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_ph (__mmask8 __A, __m256i __B) +{ + return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vcvtuqq2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu64_ph (__m128i __A) +{ + return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu64_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu64_ph (__m256i __A) +{ + return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m256i __C) +{ + return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu64_ph (__mmask8 __A, __m256i __B) +{ + return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vcvtph2w. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epi16 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvtph2w128_mask (__A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epi16 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvtph2w128_mask (__C, ( __v8hi) __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epi16 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvtph2w128_mask (__B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epi16 (__m256h __A) +{ + return (__m256i) + __builtin_ia32_vcvtph2w256_mask (__A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epi16 (__m256i __A, __mmask16 __B, __m256h __C) +{ + return (__m256i) + __builtin_ia32_vcvtph2w256_mask (__C, ( __v16hi) __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epi16 (__mmask16 __A, __m256h __B) +{ + return (__m256i) + __builtin_ia32_vcvtph2w256_mask (__B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtph2uw. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_epu16 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvtph2uw128_mask (__A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_epu16 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvtph2uw128_mask (__C, ( __v8hi) __A, __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_epu16 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvtph2uw128_mask (__B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_epu16 (__m256h __A) +{ + return (__m256i) + __builtin_ia32_vcvtph2uw256_mask (__A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_epu16 (__m256i __A, __mmask16 __B, __m256h __C) +{ + return (__m256i) + __builtin_ia32_vcvtph2uw256_mask (__C, ( __v16hi) __A, __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_epu16 (__mmask16 __A, __m256h __B) +{ + return (__m256i) + __builtin_ia32_vcvtph2uw256_mask (__B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2w. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epi16 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvttph2w128_mask (__A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epi16 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvttph2w128_mask (__C, + ( __v8hi) __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epi16 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvttph2w128_mask (__B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epi16 (__m256h __A) +{ + return (__m256i) + __builtin_ia32_vcvttph2w256_mask (__A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epi16 (__m256i __A, __mmask16 __B, __m256h __C) +{ + return (__m256i) + __builtin_ia32_vcvttph2w256_mask (__C, + ( __v16hi) __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epi16 (__mmask16 __A, __m256h __B) +{ + return (__m256i) + __builtin_ia32_vcvttph2w256_mask (__B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvttph2uw. */ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttph_epu16 (__m128h __A) +{ + return (__m128i) + __builtin_ia32_vcvttph2uw128_mask (__A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttph_epu16 (__m128i __A, __mmask8 __B, __m128h __C) +{ + return (__m128i) + __builtin_ia32_vcvttph2uw128_mask (__C, + ( __v8hi) __A, + __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttph_epu16 (__mmask8 __A, __m128h __B) +{ + return (__m128i) + __builtin_ia32_vcvttph2uw128_mask (__B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttph_epu16 (__m256h __A) +{ + return (__m256i) + __builtin_ia32_vcvttph2uw256_mask (__A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttph_epu16 (__m256i __A, __mmask16 __B, __m256h __C) +{ + return (__m256i) + __builtin_ia32_vcvttph2uw256_mask (__C, + ( __v16hi) __A, + __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttph_epu16 (__mmask16 __A, __m256h __B) +{ + return (__m256i) + __builtin_ia32_vcvttph2uw256_mask (__B, + (__v16hi) _mm256_avx512_setzero_si256 (), + __A); +} + +/* Intrinsics vcvtw2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi16_ph (__m128i __A) +{ + return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi16_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __C, + __A, + __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi16_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi16_ph (__m256i __A) +{ + return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __A, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi16_ph (__m256h __A, __mmask16 __B, __m256i __C) +{ + return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __C, + __A, + __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi16_ph (__mmask16 __A, __m256i __B) +{ + return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __B, + _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vcvtuw2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu16_ph (__m128i __A) +{ + return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu16_ph (__m128h __A, __mmask8 __B, __m128i __C) +{ + return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu16_ph (__mmask8 __A, __m128i __B) +{ + return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu16_ph (__m256i __A) +{ + return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __A, + _mm256_setzero_ph (), + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu16_ph (__m256h __A, __mmask16 __B, __m256i __C) +{ + return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __C, __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu16_ph (__mmask16 __A, __m256i __B) +{ + return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __B, + _mm256_setzero_ph (), + __A); +} + +/* Intrinsics vcvtph2pd. */ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_pd (__m128h __A) +{ + return __builtin_ia32_vcvtph2pd128_mask (__A, + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_pd (__m128d __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2pd128_mask (__C, __A, __B); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_pd (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2pd128_mask (__B, _mm_avx512_setzero_pd (), __A); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_pd (__m128h __A) +{ + return __builtin_ia32_vcvtph2pd256_mask (__A, + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_pd (__m256d __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2pd256_mask (__C, __A, __B); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_pd (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2pd256_mask (__B, + _mm256_avx512_setzero_pd (), + __A); +} + +/* Intrinsics vcvtph2ps. */ +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtxph_ps (__m128h __A) +{ + return __builtin_ia32_vcvtph2psx128_mask (__A, + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtxph_ps (__m128 __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2psx128_mask (__C, __A, __B); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtxph_ps (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2psx128_mask (__B, _mm_avx512_setzero_ps (), __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtxph_ps (__m128h __A) +{ + return __builtin_ia32_vcvtph2psx256_mask (__A, + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtxph_ps (__m256 __A, __mmask8 __B, __m128h __C) +{ + return __builtin_ia32_vcvtph2psx256_mask (__C, __A, __B); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtxph_ps (__mmask8 __A, __m128h __B) +{ + return __builtin_ia32_vcvtph2psx256_mask (__B, + _mm256_avx512_setzero_ps (), + __A); +} + +/* Intrinsics vcvtxps2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtxps_ph (__m128 __A) +{ + return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtxps_ph (__m128h __A, __mmask8 __B, __m128 __C) +{ + return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtxps_ph (__mmask8 __A, __m128 __B) +{ + return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtxps_ph (__m256 __A) +{ + return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtxps_ph (__m128h __A, __mmask8 __B, __m256 __C) +{ + return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtxps_ph (__mmask8 __A, __m256 __B) +{ + return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vcvtpd2ph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_ph (__m128d __A) +{ + return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m128d __C) +{ + return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_ph (__mmask8 __A, __m128d __B) +{ + return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __B, + _mm_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_ph (__m256d __A) +{ + return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __A, + _mm_setzero_ph (), + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m256d __C) +{ + return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __C, __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_ph (__mmask8 __A, __m256d __B) +{ + return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __B, + _mm_setzero_ph (), + __A); +} + +/* Intrinsics vfmaddsub[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmaddsub_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h)__builtin_ia32_vfmaddsubph256_mask ((__v16hf)__A, + (__v16hf)__B, + (__v16hf)__C, + (__mmask16)-1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmaddsub_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddsubph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmaddsub_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfmaddsubph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmaddsub_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddsubph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmaddsub_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h)__builtin_ia32_vfmaddsubph128_mask ((__v8hf)__A, + (__v8hf)__B, + (__v8hf)__C, + (__mmask8)-1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmaddsub_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddsubph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmaddsub_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmaddsubph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmaddsub_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddsubph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vfmsubadd[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsubadd_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsubadd_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsubadd_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfmsubaddph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsubadd_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubaddph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsubadd_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsubadd_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsubadd_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmsubaddph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsubadd_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubaddph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vfmadd[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmadd_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmadd_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmadd_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfmaddph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmadd_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmaddph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vfnmadd[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmadd_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmadd_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmaddph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmadd_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfnmaddph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmadd_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmaddph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmaddph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfnmaddph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmaddph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vfmsub[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsub_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsub_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsub_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfmsubph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsub_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmsubph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfmsubph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmsubph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vfnmsub[132,213,231]ph. */ +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmsub_ph (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmsubph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) -1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmsub_ph (__m256h __A, __mmask16 __U, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmsubph256_mask ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmsub_ph (__m256h __A, __m256h __B, __m256h __C, + __mmask16 __U) +{ + return (__m256h) __builtin_ia32_vfnmsubph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmsub_ph (__mmask16 __U, __m256h __A, __m256h __B, + __m256h __C) +{ + return (__m256h) __builtin_ia32_vfnmsubph256_maskz ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, + (__mmask16) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_ph (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmsubph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) -1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_ph (__m128h __A, __mmask8 __U, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmsubph128_mask ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_ph (__m128h __A, __m128h __B, __m128h __C, + __mmask8 __U) +{ + return (__m128h) __builtin_ia32_vfnmsubph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_ph (__mmask8 __U, __m128h __A, __m128h __B, + __m128h __C) +{ + return (__m128h) __builtin_ia32_vfnmsubph128_maskz ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, + (__mmask8) + __U); +} + +/* Intrinsics vf[,c]maddcph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_pch (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmaddcph128 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcph128_mask ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D) +{ + return (__m128h) + __builtin_ia32_vfmaddcph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D) +{ + return (__m128h) __builtin_ia32_vfmaddcph128_maskz ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmadd_pch (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmaddcph256 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D) +{ + return (__m256h) + __builtin_ia32_vfmaddcph256_mask ((__v16hf) __A, + (__v16hf) __C, + (__v16hf) __D, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D) +{ + return (__m256h) + __builtin_ia32_vfmaddcph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, __D); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D) +{ + return (__m256h)__builtin_ia32_vfmaddcph256_maskz ((__v16hf) __B, + (__v16hf) __C, + (__v16hf) __D, __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfcmaddcph128 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcph128_mask ((__v8hf) __A, + (__v8hf) __C, + (__v8hf) __D, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D) +{ + return (__m128h) + __builtin_ia32_vfcmaddcph128_mask3 ((__v8hf) __A, + (__v8hf) __B, + (__v8hf) __C, __D); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D) +{ + return (__m128h)__builtin_ia32_vfcmaddcph128_maskz ((__v8hf) __B, + (__v8hf) __C, + (__v8hf) __D, __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfcmaddcph256 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fcmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D) +{ + return (__m256h) + __builtin_ia32_vfcmaddcph256_mask ((__v16hf) __A, + (__v16hf) __C, + (__v16hf) __D, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D) +{ + return (__m256h) + __builtin_ia32_vfcmaddcph256_mask3 ((__v16hf) __A, + (__v16hf) __B, + (__v16hf) __C, __D); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fcmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D) +{ + return (__m256h) __builtin_ia32_vfcmaddcph256_maskz ((__v16hf) __B, + (__v16hf) __C, + (__v16hf) __D, __A); +} + +/* Intrinsics vf[,c]mulcph. */ +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmul_pch (__m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfmulcph128 ((__v8hf) __A, (__v8hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmul_pch (__mmask8 __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmul_pch (__m256h __A, __m256h __B) +{ + return (__m256h) __builtin_ia32_vfmulcph256 ((__v16hf) __A, + (__v16hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D) +{ + return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __C, + (__v16hf) __D, + (__v16hf) __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmul_pch (__mmask8 __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __B, + (__v16hf) __C, + _mm256_setzero_ph (), + __A); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fcmul_pch (__m128h __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_vfcmulcph128 ((__v8hf) __A, + (__v8hf) __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fcmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D) +{ + return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __C, + (__v8hf) __D, + (__v8hf) __A, __B); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fcmul_pch (__mmask8 __A, __m128h __B, __m128h __C) +{ + return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __B, + (__v8hf) __C, + _mm_setzero_ph (), + __A); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fcmul_pch (__m256h __A, __m256h __B) +{ + return (__m256h) __builtin_ia32_vfcmulcph256 ((__v16hf) __A, (__v16hf) __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fcmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D) +{ + return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __C, + (__v16hf) __D, + (__v16hf) __A, __B); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fcmul_pch (__mmask8 __A, __m256h __B, __m256h __C) +{ + return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __B, + (__v16hf) __C, + _mm256_setzero_ph (), + __A); +} + +#define _MM256_REDUCE_OP(op) \ + __m128h __T1 = (__m128h) _mm256_avx512_extractf128_pd ((__m256d) __A, 0); \ + __m128h __T2 = (__m128h) _mm256_avx512_extractf128_pd ((__m256d) __A, 1); \ + __m128h __T3 = (__T1 op __T2); \ + __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \ + (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \ + __m128h __T5 = (__T3) op (__T4); \ + __m128h __T6 = (__m128h) __builtin_shuffle (__T5, \ + (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \ + __m128h __T7 = __T5 op __T6; \ + return __T7[0] op __T7[1] + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_add_ph (__m256h __A) +{ + _MM256_REDUCE_OP (+); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_mul_ph (__m256h __A) +{ + _MM256_REDUCE_OP (*); +} + +#undef _MM256_REDUCE_OP +#define _MM256_REDUCE_OP(op) \ + __m128h __T1 = (__m128h) _mm256_avx512_extractf128_pd ((__m256d) __A, 0); \ + __m128h __T2 = (__m128h) _mm256_avx512_extractf128_pd ((__m256d) __A, 1); \ + __m128h __T3 = _mm_##op (__T1, __T2); \ + __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \ + (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \ + __m128h __T5 = _mm_##op (__T3, __T4); \ + __m128h __T6 = (__m128h) __builtin_shuffle (__T5, (__v8hi) { 4, 5 }); \ + __m128h __T7 = _mm_##op (__T5, __T6); \ + __m128h __T8 = (__m128h) __builtin_shuffle (__T7, (__v8hi) { 1, 0 }); \ + __m128h __T9 = _mm_##op (__T7, __T8); \ + return __T9[0] + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_min_ph (__m256h __A) +{ + _MM256_REDUCE_OP (min_ph); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_max_ph (__m256h __A) +{ + _MM256_REDUCE_OP (max_ph); +} + +#define _MM_REDUCE_OP(op) \ + __m128h __T1 = (__m128h) __builtin_shuffle (__A, \ + (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \ + __m128h __T2 = (__A) op (__T1); \ + __m128h __T3 = (__m128h) __builtin_shuffle (__T2, \ + (__v8hi){ 2, 3, 0, 1, 4, 5, 6, 7 }); \ + __m128h __T4 = __T2 op __T3; \ + return __T4[0] op __T4[1] + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_add_ph (__m128h __A) +{ + _MM_REDUCE_OP (+); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_mul_ph (__m128h __A) +{ + _MM_REDUCE_OP (*); +} + +#undef _MM_REDUCE_OP +#define _MM_REDUCE_OP(op) \ + __m128h __T1 = (__m128h) __builtin_shuffle (__A, \ + (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \ + __m128h __T2 = _mm_##op (__A, __T1); \ + __m128h __T3 = (__m128h) __builtin_shuffle (__T2, (__v8hi){ 4, 5 }); \ + __m128h __T4 = _mm_##op (__T2, __T3); \ + __m128h __T5 = (__m128h) __builtin_shuffle (__T4, (__v8hi){ 1, 0 }); \ + __m128h __T6 = _mm_##op (__T4, __T5); \ + return __T6[0] + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_min_ph (__m128h __A) +{ + _MM_REDUCE_OP (min_ph); +} + +extern __inline _Float16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_max_ph (__m128h __A) +{ + _MM_REDUCE_OP (max_ph); +} + +#undef _MM256_REDUCE_OP +#undef _MM_REDUCE_OP + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_ph (__mmask16 __U, __m256h __A, __m256h __W) +{ + return (__m256h) __builtin_ia32_movdquhi256_mask ((__v16hi) __W, + (__v16hi) __A, + (__mmask16) __U); + +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_ph (__m256h __A, __m256i __I, __m256h __B) +{ + return (__m256h) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A, + (__v16hi) __I, + (__v16hi) __B, + (__mmask16)-1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_ph (__m256i __A, __m256h __B) +{ + return (__m256h) __builtin_ia32_permvarhi256_mask ((__v16hi) __B, + (__v16hi) __A, + (__v16hi) + (_mm256_setzero_ph ()), + (__mmask16)-1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_ph (__mmask8 __U, __m128h __A, __m128h __W) +{ + return (__m128h) __builtin_ia32_movdquhi128_mask ((__v8hi) __W, + (__v8hi) __A, + (__mmask8) __U); + +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_ph (__m128h __A, __m128i __I, __m128h __B) +{ + return (__m128h) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A, + (__v8hi) __I, + (__v8hi) __B, + (__mmask8)-1); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutexvar_ph (__m128i __A, __m128h __B) +{ + return (__m128h) __builtin_ia32_permvarhi128_mask ((__v8hi) __B, + (__v8hi) __A, + (__v8hi) + (_mm_setzero_ph ()), + (__mmask8)-1); +} + +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex __a; + float __b; + } __u = { .__a = __A }; + + return (__m256h) _mm256_avx512_set1_ps (__u.__b); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex __a; + float __b; + } __u = { .__a = __A }; + + return (__m128h) _mm_avx512_set1_ps (__u.__b); +} + +// intrinsics below are alias for f*mul_*ch +#define _mm_mul_pch(A, B) _mm_fmul_pch ((A), (B)) +#define _mm_mask_mul_pch(W, U, A, B) _mm_mask_fmul_pch ((W), (U), (A), (B)) +#define _mm_maskz_mul_pch(U, A, B) _mm_maskz_fmul_pch ((U), (A), (B)) +#define _mm256_mul_pch(A, B) _mm256_fmul_pch ((A), (B)) +#define _mm256_mask_mul_pch(W, U, A, B) \ + _mm256_mask_fmul_pch ((W), (U), (A), (B)) +#define _mm256_maskz_mul_pch(U, A, B) _mm256_maskz_fmul_pch ((U), (A), (B)) + +#define _mm_cmul_pch(A, B) _mm_fcmul_pch ((A), (B)) +#define _mm_mask_cmul_pch(W, U, A, B) _mm_mask_fcmul_pch ((W), (U), (A), (B)) +#define _mm_maskz_cmul_pch(U, A, B) _mm_maskz_fcmul_pch ((U), (A), (B)) +#define _mm256_cmul_pch(A, B) _mm256_fcmul_pch ((A), (B)) +#define _mm256_mask_cmul_pch(W, U, A, B) \ + _mm256_mask_fcmul_pch ((W), (U), (A), (B)) +#define _mm256_maskz_cmul_pch(U, A, B) _mm256_maskz_fcmul_pch((U), (A), (B)) + +#ifdef __DISABLE_AVX512FP16VL__ +#undef __DISABLE_AVX512FP16VL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512FP16VL__ */ + +#endif /* __AVX512FP16VLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512ifmaintrin.h b/template/sysroot/include/avx512ifmaintrin.h new file mode 100644 index 0000000..eb09c97 --- /dev/null +++ b/template/sysroot/include/avx512ifmaintrin.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512IFMAINTRIN_H_INCLUDED +#define _AVX512IFMAINTRIN_H_INCLUDED + +#if !defined (__AVX512IFMA__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512ifma,evex512") +#define __DISABLE_AVX512IFMA__ +#endif /* __AVX512IFMA__ */ + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_madd52lo_epu64 (__m512i __X, __m512i __Y, __m512i __Z) +{ + return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) __Z, + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_madd52hi_epu64 (__m512i __X, __m512i __Y, __m512i __Z) +{ + return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __X, + (__v8di) __Y, + (__v8di) __Z, + (__mmask8) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_madd52lo_epu64 (__m512i __W, __mmask8 __M, __m512i __X, + __m512i __Y) +{ + return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __W, + (__v8di) __X, + (__v8di) __Y, + (__mmask8) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_madd52hi_epu64 (__m512i __W, __mmask8 __M, __m512i __X, + __m512i __Y) +{ + return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __W, + (__v8di) __X, + (__v8di) __Y, + (__mmask8) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_madd52lo_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z) +{ + return (__m512i) __builtin_ia32_vpmadd52luq512_maskz ((__v8di) __X, + (__v8di) __Y, + (__v8di) __Z, + (__mmask8) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_madd52hi_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z) +{ + return (__m512i) __builtin_ia32_vpmadd52huq512_maskz ((__v8di) __X, + (__v8di) __Y, + (__v8di) __Z, + (__mmask8) __M); +} + +#ifdef __DISABLE_AVX512IFMA__ +#undef __DISABLE_AVX512IFMA__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512IFMA__ */ + +#endif /* _AVX512IFMAINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512ifmavlintrin.h b/template/sysroot/include/avx512ifmavlintrin.h new file mode 100644 index 0000000..a8171a1 --- /dev/null +++ b/template/sysroot/include/avx512ifmavlintrin.h @@ -0,0 +1,145 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512IFMAVLINTRIN_H_INCLUDED +#define _AVX512IFMAVLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512IFMA__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512ifma,avx512vl,no-evex512") +#define __DISABLE_AVX512IFMAVL__ +#endif /* __AVX512IFMAVL__ */ + +#define _mm_madd52lo_epu64(A, B, C) \ + ((__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) (A), \ + (__v2di) (B), \ + (__v2di) (C))) + +#define _mm_madd52hi_epu64(A, B, C) \ + ((__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) (A), \ + (__v2di) (B), \ + (__v2di) (C))) + +#define _mm256_madd52lo_epu64(A, B, C) \ + ((__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) (A), \ + (__v4di) (B), \ + (__v4di) (C))) + + +#define _mm256_madd52hi_epu64(A, B, C) \ + ((__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) (A), \ + (__v4di) (B), \ + (__v4di) (C))) + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_vpmadd52luq128_mask ((__v2di) __W, + (__v2di) __X, + (__v2di) __Y, + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_vpmadd52huq128_mask ((__v2di) __W, + (__v2di) __X, + (__v2di) __Y, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_vpmadd52luq256_mask ((__v4di) __W, + (__v4di) __X, + (__v4di) __Y, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_vpmadd52huq256_mask ((__v4di) __W, + (__v4di) __X, + (__v4di) __Y, + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) +{ + return (__m128i) __builtin_ia32_vpmadd52luq128_maskz ((__v2di) __X, + (__v2di) __Y, + (__v2di) __Z, + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) +{ + return (__m128i) __builtin_ia32_vpmadd52huq128_maskz ((__v2di) __X, + (__v2di) __Y, + (__v2di) __Z, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) +{ + return (__m256i) __builtin_ia32_vpmadd52luq256_maskz ((__v4di) __X, + (__v4di) __Y, + (__v4di) __Z, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) +{ + return (__m256i) __builtin_ia32_vpmadd52huq256_maskz ((__v4di) __X, + (__v4di) __Y, + (__v4di) __Z, + (__mmask8) __M); +} + +#ifdef __DISABLE_AVX512IFMAVL__ +#undef __DISABLE_AVX512IFMAVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512IFMAVL__ */ + +#endif /* _AVX512IFMAVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512pfintrin.h b/template/sysroot/include/avx512pfintrin.h new file mode 100644 index 0000000..5ad87d1 --- /dev/null +++ b/template/sysroot/include/avx512pfintrin.h @@ -0,0 +1,269 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512PFINTRIN_H_INCLUDED +#define _AVX512PFINTRIN_H_INCLUDED + +#ifndef __AVX512PF__ +#pragma GCC push_options +#pragma GCC target("avx512pf,evex512") +#define __DISABLE_AVX512PF__ +#endif /* __AVX512PF__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef long long __v8di __attribute__ ((__vector_size__ (64))); +typedef int __v16si __attribute__ ((__vector_size__ (64))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__)); + +typedef unsigned char __mmask8; +typedef unsigned short __mmask16; + +#ifdef __OPTIMIZE__ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i32gather_pd (__m256i __index, void const *__addr, + int __scale, int __hint) +{ + __builtin_ia32_gatherpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i32gather_ps (__m512i __index, void const *__addr, + int __scale, int __hint) +{ + __builtin_ia32_gatherpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i32gather_pd (__m256i __index, __mmask8 __mask, + void const *__addr, int __scale, int __hint) +{ + __builtin_ia32_gatherpfdpd (__mask, (__v8si) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i32gather_ps (__m512i __index, __mmask16 __mask, + void const *__addr, int __scale, int __hint) +{ + __builtin_ia32_gatherpfdps (__mask, (__v16si) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i64gather_pd (__m512i __index, void const *__addr, + int __scale, int __hint) +{ + __builtin_ia32_gatherpfqpd ((__mmask8) 0xFF, (__v8di) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i64gather_ps (__m512i __index, void const *__addr, + int __scale, int __hint) +{ + __builtin_ia32_gatherpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i64gather_pd (__m512i __index, __mmask8 __mask, + void const *__addr, int __scale, int __hint) +{ + __builtin_ia32_gatherpfqpd (__mask, (__v8di) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i64gather_ps (__m512i __index, __mmask8 __mask, + void const *__addr, int __scale, int __hint) +{ + __builtin_ia32_gatherpfqps (__mask, (__v8di) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i32scatter_pd (void *__addr, __m256i __index, int __scale, + int __hint) +{ + __builtin_ia32_scatterpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i32scatter_ps (void *__addr, __m512i __index, int __scale, + int __hint) +{ + __builtin_ia32_scatterpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i32scatter_pd (void *__addr, __mmask8 __mask, + __m256i __index, int __scale, int __hint) +{ + __builtin_ia32_scatterpfdpd (__mask, (__v8si) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i32scatter_ps (void *__addr, __mmask16 __mask, + __m512i __index, int __scale, int __hint) +{ + __builtin_ia32_scatterpfdps (__mask, (__v16si) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i64scatter_pd (void *__addr, __m512i __index, int __scale, + int __hint) +{ + __builtin_ia32_scatterpfqpd ((__mmask8) 0xFF, (__v8di) __index,__addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_prefetch_i64scatter_ps (void *__addr, __m512i __index, int __scale, + int __hint) +{ + __builtin_ia32_scatterpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr, + __scale, __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i64scatter_pd (void *__addr, __mmask8 __mask, + __m512i __index, int __scale, int __hint) +{ + __builtin_ia32_scatterpfqpd (__mask, (__v8di) __index, __addr, __scale, + __hint); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_prefetch_i64scatter_ps (void *__addr, __mmask8 __mask, + __m512i __index, int __scale, int __hint) +{ + __builtin_ia32_scatterpfqps (__mask, (__v8di) __index, __addr, __scale, + __hint); +} + +#else +#define _mm512_prefetch_i32gather_pd(INDEX, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \ + (void const *) (ADDR), (int) (SCALE), \ + (int) (HINT)) + +#define _mm512_prefetch_i32gather_ps(INDEX, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX), \ + (void const *) (ADDR), (int) (SCALE), \ + (int) (HINT)) + +#define _mm512_mask_prefetch_i32gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \ + (void const *) (ADDR), (int) (SCALE), \ + (int) (HINT)) + +#define _mm512_mask_prefetch_i32gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfdps ((__mmask16) (MASK), (__v16si)(__m512i) (INDEX),\ + (void const *) (ADDR), (int) (SCALE), \ + (int) (HINT)) + +#define _mm512_prefetch_i64gather_pd(INDEX, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_prefetch_i64gather_ps(INDEX, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i64gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i64gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \ + __builtin_ia32_gatherpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_prefetch_i32scatter_pd(ADDR, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_prefetch_i32scatter_ps(ADDR, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX),\ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i32scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i32scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfdps ((__mmask16) (MASK), \ + (__v16si)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_prefetch_i64scatter_pd(ADDR, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_prefetch_i64scatter_ps(ADDR, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i64scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) + +#define _mm512_mask_prefetch_i64scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \ + __builtin_ia32_scatterpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \ + (void *) (ADDR), (int) (SCALE), (int) (HINT)) +#endif + +#ifdef __DISABLE_AVX512PF__ +#undef __DISABLE_AVX512PF__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512PF__ */ + +#endif /* _AVX512PFINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vbmi2intrin.h b/template/sysroot/include/avx512vbmi2intrin.h new file mode 100644 index 0000000..0ac6e32 --- /dev/null +++ b/template/sysroot/include/avx512vbmi2intrin.h @@ -0,0 +1,545 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef __AVX512VBMI2INTRIN_H_INCLUDED +#define __AVX512VBMI2INTRIN_H_INCLUDED + +#if !defined(__AVX512VBMI2__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vbmi2,evex512") +#define __DISABLE_AVX512VBMI2__ +#endif /* __AVX512VBMI2__ */ + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdi_epi16 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)__A, (__v32hi) __B, + __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdi_epi32 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)__A, (__v16si) __B, + __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__C, + (__v16si) __D, __E, (__v16si) __A, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__B, + (__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdi_epi64 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)__A, (__v8di) __B, __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__C, (__v8di) __D, + __E, (__v8di) __A, (__mmask8)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__B, (__v8di) __C, + __D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldi_epi16 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)__A, (__v32hi) __B, + __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldi_epi32 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshld_v16si ((__v16si)__A, (__v16si) __B, + __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__C, + (__v16si) __D, __E, (__v16si) __A, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__B, + (__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldi_epi64 (__m512i __A, __m512i __B, int __C) +{ + return (__m512i) __builtin_ia32_vpshld_v8di ((__v8di)__A, (__v8di) __B, __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__C, (__v8di) __D, + __E, (__v8di) __A, (__mmask8)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__B, (__v8di) __C, + __D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A); +} +#else +#define _mm512_shrdi_epi16(A, B, C) \ + ((__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)(__m512i)(A), \ + (__v32hi)(__m512i)(B),(int)(C))) +#define _mm512_shrdi_epi32(A, B, C) \ + ((__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B),(int)(C))) +#define _mm512_mask_shrdi_epi32(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(C), \ + (__v16si)(__m512i)(D), \ + (int)(E), \ + (__v16si)(__m512i)(A), \ + (__mmask16)(B))) +#define _mm512_maskz_shrdi_epi32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(B), \ + (__v16si)(__m512i)(C),(int)(D), \ + (__v16si)(__m512i)_mm512_setzero_si512 (), \ + (__mmask16)(A))) +#define _mm512_shrdi_epi64(A, B, C) \ + ((__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B),(int)(C))) +#define _mm512_mask_shrdi_epi64(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(C), \ + (__v8di)(__m512i)(D), (int)(E), \ + (__v8di)(__m512i)(A), \ + (__mmask8)(B))) +#define _mm512_maskz_shrdi_epi64(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(B), \ + (__v8di)(__m512i)(C),(int)(D), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(A))) +#define _mm512_shldi_epi16(A, B, C) \ + ((__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)(__m512i)(A), \ + (__v32hi)(__m512i)(B),(int)(C))) +#define _mm512_shldi_epi32(A, B, C) \ + ((__m512i) __builtin_ia32_vpshld_v16si ((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B),(int)(C))) +#define _mm512_mask_shldi_epi32(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(C), \ + (__v16si)(__m512i)(D), \ + (int)(E), \ + (__v16si)(__m512i)(A), \ + (__mmask16)(B))) +#define _mm512_maskz_shldi_epi32(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(B), \ + (__v16si)(__m512i)(C),(int)(D), \ + (__v16si)(__m512i)_mm512_setzero_si512 (), \ + (__mmask16)(A))) +#define _mm512_shldi_epi64(A, B, C) \ + ((__m512i) __builtin_ia32_vpshld_v8di ((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(C))) +#define _mm512_mask_shldi_epi64(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(C), \ + (__v8di)(__m512i)(D), (int)(E), \ + (__v8di)(__m512i)(A), \ + (__mmask8)(B))) +#define _mm512_maskz_shldi_epi64(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(B), \ + (__v8di)(__m512i)(C),(int)(D), \ + (__v8di)(__m512i)_mm512_setzero_si512 (), \ + (__mmask8)(A))) +#endif + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdv_epi16 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshrdv_v32hi ((__v32hi)__A, (__v32hi) __B, + (__v32hi) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdv_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshrdv_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shrdv_epi64 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshrdv_v8di ((__v8di)__A, (__v8di) __B, + (__v8di) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v8di_mask ((__v8di)__A, (__v8di) __C, + (__v8di) __D, (__mmask8)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v8di_maskz ((__v8di)__B, (__v8di) __C, + (__v8di) __D, (__mmask8)__A); +} +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldv_epi16 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshldv_v32hi ((__v32hi)__A, (__v32hi) __B, + (__v32hi) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldv_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshldv_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_shldv_epi64 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpshldv_v8di ((__v8di)__A, (__v8di) __B, + (__v8di) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v8di_mask ((__v8di)__A, (__v8di) __C, + (__v8di) __D, (__mmask8)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v8di_maskz ((__v8di)__B, (__v8di) __C, + (__v8di) __D, (__mmask8)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_epi8 (__m512i __A, __mmask64 __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__C, + (__v64qi)__A, (__mmask64)__B); +} + + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_epi8 (__mmask64 __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__B, + (__v64qi)_mm512_setzero_si512 (), (__mmask64)__A); +} + + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_epi8 (void * __A, __mmask64 __B, __m512i __C) +{ + __builtin_ia32_compressstoreuqi512_mask ((__v64qi *) __A, (__v64qi) __C, + (__mmask64) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compress_epi16 (__m512i __A, __mmask32 __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__C, + (__v32hi)__A, (__mmask32)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_compress_epi16 (__mmask32 __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__B, + (__v32hi)_mm512_setzero_si512 (), (__mmask32)__A); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_compressstoreu_epi16 (void * __A, __mmask32 __B, __m512i __C) +{ + __builtin_ia32_compressstoreuhi512_mask ((__v32hi *) __A, (__v32hi) __C, + (__mmask32) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_epi8 (__m512i __A, __mmask64 __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_expandqi512_mask ((__v64qi) __C, + (__v64qi) __A, + (__mmask64) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_epi8 (__mmask64 __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_expandqi512_maskz ((__v64qi) __B, + (__v64qi) _mm512_setzero_si512 (), (__mmask64) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_epi8 (__m512i __A, __mmask64 __B, const void * __C) +{ + return (__m512i) __builtin_ia32_expandloadqi512_mask ((const __v64qi *) __C, + (__v64qi) __A, (__mmask64) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_epi8 (__mmask64 __A, const void * __B) +{ + return (__m512i) __builtin_ia32_expandloadqi512_maskz ((const __v64qi *) __B, + (__v64qi) _mm512_setzero_si512 (), (__mmask64) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expand_epi16 (__m512i __A, __mmask32 __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_expandhi512_mask ((__v32hi) __C, + (__v32hi) __A, + (__mmask32) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expand_epi16 (__mmask32 __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_expandhi512_maskz ((__v32hi) __B, + (__v32hi) _mm512_setzero_si512 (), (__mmask32) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_expandloadu_epi16 (__m512i __A, __mmask32 __B, const void * __C) +{ + return (__m512i) __builtin_ia32_expandloadhi512_mask ((const __v32hi *) __C, + (__v32hi) __A, (__mmask32) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_expandloadu_epi16 (__mmask32 __A, const void * __B) +{ + return (__m512i) __builtin_ia32_expandloadhi512_maskz ((const __v32hi *) __B, + (__v32hi) _mm512_setzero_si512 (), (__mmask32) __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__C, + (__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__B, + (__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D, + int __E) +{ + return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__C, + (__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D) +{ + return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__B, + (__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A); +} + +#else +#define _mm512_mask_shrdi_epi16(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(C), \ + (__v32hi)(__m512i)(D), \ + (int)(E), \ + (__v32hi)(__m512i)(A), \ + (__mmask32)(B))) +#define _mm512_maskz_shrdi_epi16(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(B), \ + (__v32hi)(__m512i)(C),(int)(D), \ + (__v32hi)(__m512i)_mm512_setzero_si512 (), \ + (__mmask32)(A))) +#define _mm512_mask_shldi_epi16(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(C), \ + (__v32hi)(__m512i)(D), \ + (int)(E), \ + (__v32hi)(__m512i)(A), \ + (__mmask32)(B))) +#define _mm512_maskz_shldi_epi16(A, B, C, D) \ + ((__m512i) \ + __builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(B), \ + (__v32hi)(__m512i)(C),(int)(D), \ + (__v32hi)(__m512i)_mm512_setzero_si512 (), \ + (__mmask32)(A))) +#endif + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shrdv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v32hi_mask ((__v32hi)__A, + (__v32hi) __C, (__v32hi) __D, (__mmask32)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shrdv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshrdv_v32hi_maskz ((__v32hi)__B, + (__v32hi) __C, (__v32hi) __D, (__mmask32)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_shldv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v32hi_mask ((__v32hi)__A, + (__v32hi) __C, (__v32hi) __D, (__mmask32)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_shldv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpshldv_v32hi_maskz ((__v32hi)__B, + (__v32hi) __C, (__v32hi) __D, (__mmask32)__A); +} + +#ifdef __DISABLE_AVX512VBMI2__ +#undef __DISABLE_AVX512VBMI2__ + +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VBMI2__ */ + +#endif /* __AVX512VBMI2INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vbmi2vlintrin.h b/template/sysroot/include/avx512vbmi2vlintrin.h new file mode 100644 index 0000000..bb37872 --- /dev/null +++ b/template/sysroot/include/avx512vbmi2vlintrin.h @@ -0,0 +1,1022 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VBMI2VLINTRIN_H_INCLUDED +#define _AVX512VBMI2VLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512VBMI2__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vbmi2,avx512vl,no-evex512") +#define __DISABLE_AVX512VBMI2VL__ +#endif /* __AVX512VBMIVL__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_epi8 (__m128i __A, __mmask16 __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi)__C, + (__v16qi)__A, (__mmask16)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_epi8 (__mmask16 __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __B, + (__v16qi) _mm_avx512_setzero_si128 (), (__mmask16) __A); +} + + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_epi16 (void * __A, __mmask16 __B, __m256i __C) +{ + __builtin_ia32_compressstoreuhi256_mask ((__v16hi *) __A, (__v16hi) __C, + (__mmask16) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_epi16 (__m128i __A, __mmask8 __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi)__C, (__v8hi)__A, + (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_epi16 (__mmask8 __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __B, + (__v8hi) _mm_avx512_setzero_si128 (), (__mmask8) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_epi16 (__m256i __A, __mmask16 __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi)__C, + (__v16hi)__A, (__mmask16)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_epi16 (__mmask16 __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __B, + (__v16hi) _mm256_avx512_setzero_si256 (), (__mmask16) __A); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_epi8 (void * __A, __mmask16 __B, __m128i __C) +{ + __builtin_ia32_compressstoreuqi128_mask ((__v16qi *) __A, (__v16qi) __C, + (__mmask16) __B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_epi16 (void * __A, __mmask8 __B, __m128i __C) +{ + __builtin_ia32_compressstoreuhi128_mask ((__v8hi *) __A, (__v8hi) __C, + (__mmask8) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_epi8 (__m128i __A, __mmask16 __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __C, + (__v16qi) __A, + (__mmask16) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_epi8 (__mmask16 __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_expandqi128_maskz ((__v16qi) __B, + (__v16qi) _mm_avx512_setzero_si128 (), (__mmask16) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_epi8 (__m128i __A, __mmask16 __B, const void * __C) +{ + return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *) __C, + (__v16qi) __A, (__mmask16) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_epi8 (__mmask16 __A, const void * __B) +{ + return (__m128i) __builtin_ia32_expandloadqi128_maskz ((const __v16qi *) __B, + (__v16qi) _mm_avx512_setzero_si128 (), (__mmask16) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_epi16 (__m128i __A, __mmask8 __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __C, + (__v8hi) __A, + (__mmask8) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_epi16 (__mmask8 __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_expandhi128_maskz ((__v8hi) __B, + (__v8hi) _mm_avx512_setzero_si128 (), (__mmask8) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_epi16 (__m128i __A, __mmask8 __B, const void * __C) +{ + return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *) __C, + (__v8hi) __A, (__mmask8) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_epi16 (__mmask8 __A, const void * __B) +{ + return (__m128i) __builtin_ia32_expandloadhi128_maskz ((const __v8hi *) __B, + (__v8hi) _mm_avx512_setzero_si128 (), (__mmask8) __A); +} +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_epi16 (__m256i __A, __mmask16 __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_expandhi256_mask ((__v16hi) __C, + (__v16hi) __A, + (__mmask16) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_epi16 (__mmask16 __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_expandhi256_maskz ((__v16hi) __B, + (__v16hi) _mm256_avx512_setzero_si256 (), (__mmask16) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_epi16 (__m256i __A, __mmask16 __B, const void * __C) +{ + return (__m256i) __builtin_ia32_expandloadhi256_mask ((const __v16hi *) __C, + (__v16hi) __A, (__mmask16) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_epi16 (__mmask16 __A, const void * __B) +{ + return (__m256i) __builtin_ia32_expandloadhi256_maskz ((const __v16hi *) __B, + (__v16hi) _mm256_avx512_setzero_si256 (), (__mmask16) __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdi_epi16 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshrd_v16hi ((__v16hi)__A, (__v16hi) __B, + __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdi_epi16 (__m256i __A, __mmask16 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshrd_v16hi_mask ((__v16hi)__C, + (__v16hi) __D, __E, (__v16hi) __A, (__mmask16)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdi_epi16 (__mmask16 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshrd_v16hi_mask ((__v16hi)__B, + (__v16hi) __C, __D, (__v16hi) _mm256_avx512_setzero_si256 (), (__mmask16)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdi_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshrd_v8si_mask ((__v8si)__C, (__v8si) __D, + __E, (__v8si) __A, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdi_epi32 (__mmask8 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshrd_v8si_mask ((__v8si)__B, (__v8si) __C, + __D, (__v8si) _mm256_avx512_setzero_si256 (), (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdi_epi32 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshrd_v8si ((__v8si)__A, (__v8si) __B, __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdi_epi64 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshrd_v4di_mask ((__v4di)__C, (__v4di) __D, + __E, (__v4di) __A, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdi_epi64 (__mmask8 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshrd_v4di_mask ((__v4di)__B, (__v4di) __C, + __D, (__v4di) _mm256_avx512_setzero_si256 (), (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdi_epi64 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshrd_v4di ((__v4di)__A, (__v4di) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdi_epi16 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshrd_v8hi_mask ((__v8hi)__C, (__v8hi) __D, + __E, (__v8hi) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdi_epi16 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshrd_v8hi_mask ((__v8hi)__B, (__v8hi) __C, + __D, (__v8hi) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdi_epi16 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshrd_v8hi ((__v8hi)__A, (__v8hi) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdi_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshrd_v4si_mask ((__v4si)__C, (__v4si) __D, + __E, (__v4si) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdi_epi32 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshrd_v4si_mask ((__v4si)__B, (__v4si) __C, + __D, (__v4si) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdi_epi32 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshrd_v4si ((__v4si)__A, (__v4si) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdi_epi64 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshrd_v2di_mask ((__v2di)__C, (__v2di) __D, + __E, (__v2di) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdi_epi64 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshrd_v2di_mask ((__v2di)__B, (__v2di) __C, + __D, (__v2di) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdi_epi64 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshrd_v2di ((__v2di)__A, (__v2di) __B, __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldi_epi16 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshld_v16hi ((__v16hi)__A, (__v16hi) __B, + __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldi_epi16 (__m256i __A, __mmask16 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshld_v16hi_mask ((__v16hi)__C, + (__v16hi) __D, __E, (__v16hi) __A, (__mmask16)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldi_epi16 (__mmask16 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshld_v16hi_mask ((__v16hi)__B, + (__v16hi) __C, __D, (__v16hi) _mm256_avx512_setzero_si256 (), (__mmask16)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldi_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshld_v8si_mask ((__v8si)__C, (__v8si) __D, + __E, (__v8si) __A, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldi_epi32 (__mmask8 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshld_v8si_mask ((__v8si)__B, (__v8si) __C, + __D, (__v8si) _mm256_avx512_setzero_si256 (), (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldi_epi32 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshld_v8si ((__v8si)__A, (__v8si) __B, __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldi_epi64 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D, + int __E) +{ + return (__m256i)__builtin_ia32_vpshld_v4di_mask ((__v4di)__C, (__v4di) __D, + __E, (__v4di) __A, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldi_epi64 (__mmask8 __A, __m256i __B, __m256i __C, int __D) +{ + return (__m256i)__builtin_ia32_vpshld_v4di_mask ((__v4di)__B, (__v4di) __C, + __D, (__v4di) _mm256_avx512_setzero_si256 (), (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldi_epi64 (__m256i __A, __m256i __B, int __C) +{ + return (__m256i) __builtin_ia32_vpshld_v4di ((__v4di)__A, (__v4di) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldi_epi16 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshld_v8hi_mask ((__v8hi)__C, (__v8hi) __D, + __E, (__v8hi) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldi_epi16 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshld_v8hi_mask ((__v8hi)__B, (__v8hi) __C, + __D, (__v8hi) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldi_epi16 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshld_v8hi ((__v8hi)__A, (__v8hi) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldi_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshld_v4si_mask ((__v4si)__C, (__v4si) __D, + __E, (__v4si) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldi_epi32 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshld_v4si_mask ((__v4si)__B, (__v4si) __C, + __D, (__v4si) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldi_epi32 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshld_v4si ((__v4si)__A, (__v4si) __B, __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldi_epi64 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D, + int __E) +{ + return (__m128i)__builtin_ia32_vpshld_v2di_mask ((__v2di)__C, (__v2di) __D, + __E, (__v2di) __A, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldi_epi64 (__mmask8 __A, __m128i __B, __m128i __C, int __D) +{ + return (__m128i)__builtin_ia32_vpshld_v2di_mask ((__v2di)__B, (__v2di) __C, + __D, (__v2di) _mm_avx512_setzero_si128 (), (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldi_epi64 (__m128i __A, __m128i __B, int __C) +{ + return (__m128i) __builtin_ia32_vpshld_v2di ((__v2di)__A, (__v2di) __B, __C); +} +#else +#define _mm256_shrdi_epi16(A, B, C) \ + ((__m256i) __builtin_ia32_vpshrd_v16hi ((__v16hi)(__m256i)(A), \ + (__v16hi)(__m256i)(B),(int)(C))) +#define _mm256_mask_shrdi_epi16(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshrd_v16hi_mask ((__v16hi)(__m256i)(C), \ + (__v16hi)(__m256i)(D), \ + (int)(E), \ + (__v16hi)(__m256i)(A), \ + (__mmask16)(B))) +#define _mm256_maskz_shrdi_epi16(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshrd_v16hi_mask ((__v16hi)(__m256i)(B), \ + (__v16hi)(__m256i)(C),(int)(D), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask16)(A))) +#define _mm256_shrdi_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpshrd_v8si ((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B),(int)(C))) +#define _mm256_mask_shrdi_epi32(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshrd_v8si_mask ((__v8si)(__m256i)(C), \ + (__v8si)(__m256i)(D), \ + (int)(E), \ + (__v8si)(__m256i)(A), \ + (__mmask8)(B))) +#define _mm256_maskz_shrdi_epi32(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshrd_v8si_mask ((__v8si)(__m256i)(B), \ + (__v8si)(__m256i)(C),(int)(D), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(A))) +#define _mm256_shrdi_epi64(A, B, C) \ + ((__m256i) __builtin_ia32_vpshrd_v4di ((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B),(int)(C))) +#define _mm256_mask_shrdi_epi64(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshrd_v4di_mask ((__v4di)(__m256i)(C), \ + (__v4di)(__m256i)(D), (int)(E), \ + (__v4di)(__m256i)(A), \ + (__mmask8)(B))) +#define _mm256_maskz_shrdi_epi64(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshrd_v4di_mask ((__v4di)(__m256i)(B), \ + (__v4di)(__m256i)(C),(int)(D), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(A))) +#define _mm_shrdi_epi16(A, B, C) \ + ((__m128i) __builtin_ia32_vpshrd_v8hi ((__v8hi)(__m128i)(A), \ + (__v8hi)(__m128i)(B),(int)(C))) +#define _mm_mask_shrdi_epi16(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshrd_v8hi_mask ((__v8hi)(__m128i)(C), \ + (__v8hi)(__m128i)(D), (int)(E), \ + (__v8hi)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shrdi_epi16(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshrd_v8hi_mask ((__v8hi)(__m128i)(B), \ + (__v8hi)(__m128i)(C),(int)(D), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#define _mm_shrdi_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpshrd_v4si ((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B),(int)(C))) +#define _mm_mask_shrdi_epi32(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshrd_v4si_mask ((__v4si)(__m128i)(C), \ + (__v4si)(__m128i)(D), (int)(E), \ + (__v4si)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shrdi_epi32(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshrd_v4si_mask ((__v4si)(__m128i)(B), \ + (__v4si)(__m128i)(C),(int)(D), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#define _mm_shrdi_epi64(A, B, C) \ + ((__m128i) __builtin_ia32_vpshrd_v2di ((__v2di)(__m128i)(A), \ + (__v2di)(__m128i)(B),(int)(C))) +#define _mm_mask_shrdi_epi64(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshrd_v2di_mask ((__v2di)(__m128i)(C), \ + (__v2di)(__m128i)(D), (int)(E), \ + (__v2di)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shrdi_epi64(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshrd_v2di_mask ((__v2di)(__m128i)(B), \ + (__v2di)(__m128i)(C),(int)(D), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#define _mm256_shldi_epi16(A, B, C) \ + ((__m256i) __builtin_ia32_vpshld_v16hi ((__v16hi)(__m256i)(A), \ + (__v16hi)(__m256i)(B),(int)(C))) +#define _mm256_mask_shldi_epi16(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshld_v16hi_mask ((__v16hi)(__m256i)(C), \ + (__v16hi)(__m256i)(D), \ + (int)(E), \ + (__v16hi)(__m256i)(A), \ + (__mmask16)(B))) +#define _mm256_maskz_shldi_epi16(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshld_v16hi_mask ((__v16hi)(__m256i)(B), \ + (__v16hi)(__m256i)(C),(int)(D), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask16)(A))) +#define _mm256_shldi_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpshld_v8si ((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B),(int)(C))) +#define _mm256_mask_shldi_epi32(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshld_v8si_mask ((__v8si)(__m256i)(C), \ + (__v8si)(__m256i)(D), (int)(E), \ + (__v8si)(__m256i)(A), \ + (__mmask8)(B))) +#define _mm256_maskz_shldi_epi32(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshld_v8si_mask ((__v8si)(__m256i)(B), \ + (__v8si)(__m256i)(C),(int)(D), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(A))) +#define _mm256_shldi_epi64(A, B, C) \ + ((__m256i) __builtin_ia32_vpshld_v4di ((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B),(int)(C))) +#define _mm256_mask_shldi_epi64(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vpshld_v4di_mask ((__v4di)(__m256i)(C), \ + (__v4di)(__m256i)(D), (int)(E), \ + (__v4di)(__m256i)(A), \ + (__mmask8)(B))) +#define _mm256_maskz_shldi_epi64(A, B, C, D) \ + ((__m256i) \ + __builtin_ia32_vpshld_v4di_mask ((__v4di)(__m256i)(B), \ + (__v4di)(__m256i)(C),(int)(D), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(A))) +#define _mm_shldi_epi16(A, B, C) \ + ((__m128i) __builtin_ia32_vpshld_v8hi ((__v8hi)(__m128i)(A), \ + (__v8hi)(__m128i)(B),(int)(C))) +#define _mm_mask_shldi_epi16(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshld_v8hi_mask ((__v8hi)(__m128i)(C), \ + (__v8hi)(__m128i)(D), (int)(E), \ + (__v8hi)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shldi_epi16(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshld_v8hi_mask ((__v8hi)(__m128i)(B), \ + (__v8hi)(__m128i)(C),(int)(D), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#define _mm_shldi_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpshld_v4si ((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B),(int)(C))) +#define _mm_mask_shldi_epi32(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshld_v4si_mask ((__v4si)(__m128i)(C), \ + (__v4si)(__m128i)(D), (int)(E), \ + (__v4si)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shldi_epi32(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshld_v4si_mask ((__v4si)(__m128i)(B), \ + (__v4si)(__m128i)(C),(int)(D), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#define _mm_shldi_epi64(A, B, C) \ + ((__m128i) __builtin_ia32_vpshld_v2di ((__v2di)(__m128i)(A), \ + (__v2di)(__m128i)(B),(int)(C))) +#define _mm_mask_shldi_epi64(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vpshld_v2di_mask ((__v2di)(__m128i)(C), \ + (__v2di)(__m128i)(D), (int)(E), \ + (__v2di)(__m128i)(A), \ + (__mmask8)(B))) +#define _mm_maskz_shldi_epi64(A, B, C, D) \ + ((__m128i) \ + __builtin_ia32_vpshld_v2di_mask ((__v2di)(__m128i)(B), \ + (__v2di)(__m128i)(C),(int)(D), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(A))) +#endif + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdv_epi16 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshrdv_v16hi ((__v16hi)__A, (__v16hi) __B, + (__v16hi) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdv_epi16 (__m256i __A, __mmask16 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v16hi_mask ((__v16hi)__A, + (__v16hi) __C, (__v16hi) __D, (__mmask16)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdv_epi16 (__mmask16 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v16hi_maskz ((__v16hi)__B, + (__v16hi) __C, (__v16hi) __D, (__mmask16)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdv_epi32 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshrdv_v8si ((__v8si)__A, (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdv_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v8si_mask ((__v8si)__A, (__v8si) __C, + (__v8si) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdv_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v8si_maskz ((__v8si)__B, (__v8si) __C, + (__v8si) __D, (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shrdv_epi64 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshrdv_v4di ((__v4di)__A, (__v4di) __B, + (__v4di) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shrdv_epi64 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v4di_mask ((__v4di)__A, (__v4di) __C, + (__v4di) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shrdv_epi64 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshrdv_v4di_maskz ((__v4di)__B, (__v4di) __C, + (__v4di) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdv_epi16 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshrdv_v8hi ((__v8hi)__A, (__v8hi) __B, + (__v8hi) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdv_epi16 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v8hi_mask ((__v8hi)__A, (__v8hi) __C, + (__v8hi) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdv_epi16 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v8hi_maskz ((__v8hi)__B, (__v8hi) __C, + (__v8hi) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdv_epi32 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshrdv_v4si ((__v4si)__A, (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdv_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v4si_mask ((__v4si)__A, (__v4si) __C, + (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdv_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v4si_maskz ((__v4si)__B, (__v4si) __C, + (__v4si) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shrdv_epi64 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshrdv_v2di ((__v2di)__A, (__v2di) __B, + (__v2di) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shrdv_epi64 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v2di_mask ((__v2di)__A, (__v2di) __C, + (__v2di) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shrdv_epi64 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshrdv_v2di_maskz ((__v2di)__B, (__v2di) __C, + (__v2di) __D, (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldv_epi16 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshldv_v16hi ((__v16hi)__A, (__v16hi) __B, + (__v16hi) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldv_epi16 (__m256i __A, __mmask16 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v16hi_mask ((__v16hi)__A, + (__v16hi) __C, (__v16hi) __D, (__mmask16)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldv_epi16 (__mmask16 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v16hi_maskz ((__v16hi)__B, + (__v16hi) __C, (__v16hi) __D, (__mmask16)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldv_epi32 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshldv_v8si ((__v8si)__A, (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldv_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v8si_mask ((__v8si)__A, (__v8si) __C, + (__v8si) __D, (__mmask8)__B) ; +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldv_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v8si_maskz ((__v8si)__B, (__v8si) __C, + (__v8si) __D, (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shldv_epi64 (__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpshldv_v4di ((__v4di)__A, (__v4di) __B, + (__v4di) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shldv_epi64 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v4di_mask ((__v4di)__A, (__v4di) __C, + (__v4di) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shldv_epi64 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpshldv_v4di_maskz ((__v4di)__B, (__v4di) __C, + (__v4di) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldv_epi16 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshldv_v8hi ((__v8hi)__A, (__v8hi) __B, + (__v8hi) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldv_epi16 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v8hi_mask ((__v8hi)__A, (__v8hi) __C, + (__v8hi) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldv_epi16 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v8hi_maskz ((__v8hi)__B, (__v8hi) __C, + (__v8hi) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldv_epi32 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshldv_v4si ((__v4si)__A, (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldv_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v4si_mask ((__v4si)__A, (__v4si) __C, + (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldv_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v4si_maskz ((__v4si)__B, (__v4si) __C, + (__v4si) __D, (__mmask8)__A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shldv_epi64 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpshldv_v2di ((__v2di)__A, (__v2di) __B, + (__v2di) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shldv_epi64 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v2di_mask ((__v2di)__A, (__v2di) __C, + (__v2di) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shldv_epi64 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpshldv_v2di_maskz ((__v2di)__B, (__v2di) __C, + (__v2di) __D, (__mmask8)__A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_epi8 (__m256i __A, __mmask32 __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi)__C, + (__v32qi)__A, (__mmask32)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_epi8 (__mmask32 __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi) __B, + (__v32qi) _mm256_avx512_setzero_si256 (), (__mmask32) __A); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_epi8 (void * __A, __mmask32 __B, __m256i __C) +{ + __builtin_ia32_compressstoreuqi256_mask ((__v32qi *) __A, (__v32qi) __C, + (__mmask32) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_epi8 (__m256i __A, __mmask32 __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_expandqi256_mask ((__v32qi) __C, + (__v32qi) __A, + (__mmask32) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_epi8 (__mmask32 __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_expandqi256_maskz ((__v32qi) __B, + (__v32qi) _mm256_avx512_setzero_si256 (), (__mmask32) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_epi8 (__m256i __A, __mmask32 __B, const void * __C) +{ + return (__m256i) __builtin_ia32_expandloadqi256_mask ((const __v32qi *) __C, + (__v32qi) __A, (__mmask32) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_epi8 (__mmask32 __A, const void * __B) +{ + return (__m256i) __builtin_ia32_expandloadqi256_maskz ((const __v32qi *) __B, + (__v32qi) _mm256_avx512_setzero_si256 (), (__mmask32) __A); +} + +#ifdef __DISABLE_AVX512VBMI2VL__ +#undef __DISABLE_AVX512VBMI2VL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VBMIVL__ */ + +#endif /* _AVX512VBMIVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vbmiintrin.h b/template/sysroot/include/avx512vbmiintrin.h new file mode 100644 index 0000000..0db0273 --- /dev/null +++ b/template/sysroot/include/avx512vbmiintrin.h @@ -0,0 +1,158 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VBMIINTRIN_H_INCLUDED +#define _AVX512VBMIINTRIN_H_INCLUDED + +#if !defined (__AVX512VBMI__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vbmi,evex512") +#define __DISABLE_AVX512VBMI__ +#endif /* __AVX512VBMI__ */ + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_multishift_epi64_epi8 (__m512i __W, __mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_multishift_epi64_epi8 (__mmask64 __M, __m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v64qi) + _mm512_setzero_si512 (), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_multishift_epi64_epi8 (__m512i __X, __m512i __Y) +{ + return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X, + (__v64qi) __Y, + (__v64qi) + _mm512_undefined_epi32 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutexvar_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B, + (__v64qi) __A, + (__v64qi) + _mm512_undefined_epi32 (), + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutexvar_epi8 (__mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B, + (__v64qi) __A, + (__v64qi) + _mm512_setzero_si512(), + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutexvar_epi8 (__m512i __W, __mmask64 __M, __m512i __A, + __m512i __B) +{ + return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B, + (__v64qi) __A, + (__v64qi) __W, + (__mmask64) __M); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_permutex2var_epi8 (__m512i __A, __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I + /* idx */ , + (__v64qi) __A, + (__v64qi) __B, + (__mmask64) -1); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_permutex2var_epi8 (__m512i __A, __mmask64 __U, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I + /* idx */ , + (__v64qi) __A, + (__v64qi) __B, + (__mmask64) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask2_permutex2var_epi8 (__m512i __A, __m512i __I, + __mmask64 __U, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermi2varqi512_mask ((__v64qi) __A, + (__v64qi) __I + /* idx */ , + (__v64qi) __B, + (__mmask64) + __U); +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_permutex2var_epi8 (__mmask64 __U, __m512i __A, + __m512i __I, __m512i __B) +{ + return (__m512i) __builtin_ia32_vpermt2varqi512_maskz ((__v64qi) __I + /* idx */ , + (__v64qi) __A, + (__v64qi) __B, + (__mmask64) + __U); +} + +#ifdef __DISABLE_AVX512VBMI__ +#undef __DISABLE_AVX512VBMI__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VBMI__ */ + +#endif /* _AVX512VBMIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vbmivlintrin.h b/template/sysroot/include/avx512vbmivlintrin.h new file mode 100644 index 0000000..22d940e --- /dev/null +++ b/template/sysroot/include/avx512vbmivlintrin.h @@ -0,0 +1,273 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VBMIVLINTRIN_H_INCLUDED +#define _AVX512VBMIVLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512VBMI__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vbmi,avx512vl,no-evex512") +#define __DISABLE_AVX512VBMIVL__ +#endif /* __AVX512VBMIVL__ */ + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, + (__v32qi) __Y, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, + (__v32qi) __Y, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, + (__v32qi) __Y, + (__v32qi) + _mm256_avx512_undefined_si256 (), + (__mmask32) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, + (__v16qi) __Y, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, + (__v16qi) __Y, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, + (__v16qi) __Y, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B, + (__v32qi) __A, + (__v32qi) + _mm256_avx512_undefined_si256 (), + (__mmask32) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B, + (__v32qi) __A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B, + (__v32qi) __A, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutexvar_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B, + (__v16qi) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask16) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B, + (__v16qi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B, + (__v16qi) __A, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_epi8 (__m256i __A, __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I + /* idx */ , + (__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_epi8 (__m256i __A, __mmask32 __U, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I + /* idx */ , + (__v32qi) __A, + (__v32qi) __B, + (__mmask32) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_epi8 (__m256i __A, __m256i __I, + __mmask32 __U, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermi2varqi256_mask ((__v32qi) __A, + (__v32qi) __I + /* idx */ , + (__v32qi) __B, + (__mmask32) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_epi8 (__mmask32 __U, __m256i __A, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varqi256_maskz ((__v32qi) __I + /* idx */ , + (__v32qi) __A, + (__v32qi) __B, + (__mmask32) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_epi8 (__m128i __A, __m128i __I, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I + /* idx */ , + (__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_epi8 (__m128i __A, __mmask16 __U, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I + /* idx */ , + (__v16qi) __A, + (__v16qi) __B, + (__mmask16) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_epi8 (__m128i __A, __m128i __I, __mmask16 __U, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermi2varqi128_mask ((__v16qi) __A, + (__v16qi) __I + /* idx */ , + (__v16qi) __B, + (__mmask16) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_epi8 (__mmask16 __U, __m128i __A, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varqi128_maskz ((__v16qi) __I + /* idx */ , + (__v16qi) __A, + (__v16qi) __B, + (__mmask16) + __U); +} + +#ifdef __DISABLE_AVX512VBMIVL__ +#undef __DISABLE_AVX512VBMIVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VBMIVL__ */ + +#endif /* _AVX512VBMIVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vlbwintrin.h b/template/sysroot/include/avx512vlbwintrin.h new file mode 100644 index 0000000..98b9099 --- /dev/null +++ b/template/sysroot/include/avx512vlbwintrin.h @@ -0,0 +1,5248 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VLBWINTRIN_H_INCLUDED +#define _AVX512VLBWINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512BW__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vl,avx512bw,no-evex512") +#define __DISABLE_AVX512VLBW__ +#endif /* __AVX512VLBW__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef short __v16hi_u __attribute__ ((__vector_size__ (32), \ + __may_alias__, __aligned__ (1))); +typedef short __v8hi_u __attribute__ ((__vector_size__ (16), \ + __may_alias__, __aligned__ (1))); +typedef char __v32qi_u __attribute__ ((__vector_size__ (32), \ + __may_alias__, __aligned__ (1))); +typedef char __v16qi_u __attribute__ ((__vector_size__ (16), \ + __may_alias__, __aligned__ (1))); + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set1_epi32 (int __A) +{ + return _mm_avx512_set_epi32 (__A, __A, __A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set1_epi16 (short __A) +{ + return _mm_avx512_set_epi16 (__A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_set1_epi8 (char __A) +{ + return _mm_avx512_set_epi8 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set_epi16 (short __q15, short __q14, short __q13, short __q12, + short __q11, short __q10, short __q09, short __q08, + short __q07, short __q06, short __q05, short __q04, + short __q03, short __q02, short __q01, short __q00) +{ + return __extension__ (__m256i)(__v16hi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15 + }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set_epi8 (char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return __extension__ (__m256i)(__v32qi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15, + __q16, __q17, __q18, __q19, __q20, __q21, __q22, __q23, + __q24, __q25, __q26, __q27, __q28, __q29, __q30, __q31 + }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set1_epi16 (short __A) +{ + return _mm256_avx512_set_epi16 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set1_epi32 (int __A) +{ + return __extension__ (__m256i)(__v8si){ __A, __A, __A, __A, + __A, __A, __A, __A }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_set1_epi8 (char __A) +{ + return _mm256_avx512_set_epi8 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_max_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmaxsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_min_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pminsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_max_epu16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_min_epu16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminuw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_max_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_min_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminsb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_max_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmaxub128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_min_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pminub128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_epi8 (__m256i __W, __mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdquqi256_mask ((__v32qi) __A, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_max_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_min_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminsw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_max_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pmaxuw256 ((__v16hi)__A, (__v16hi)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_min_epu16 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_pminuw256 ((__v16hi)__A, (__v16hi)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_insertf128_ps (__m256 __X, __m128 __Y, const int __O) +{ + return (__m256) __builtin_ia32_vinsertf128_ps256 ((__v8sf)__X, + (__v4sf)__Y, + __O); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_extractf128_pd (__m256d __X, const int __N) +{ + return (__m128d) __builtin_ia32_vextractf128_pd256 ((__v4df)__X, __N); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_extracti128_si256 (__m256i __X, const int __M) +{ + return (__m128i) __builtin_ia32_extract128i256 ((__v4di)__X, __M); +} +#else +#define _mm256_avx512_insertf128_ps(X, Y, O) \ + ((__m256) __builtin_ia32_vinsertf128_ps256 ((__v8sf)(__m256)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(O))) + +#define _mm256_avx512_extractf128_pd(X, N) \ + ((__m128d) __builtin_ia32_vextractf128_pd256 ((__v4df)(__m256d)(X), \ + (int)(N))) + +#define _mm256_avx512_extracti128_si256(X, M) \ + ((__m128i) __builtin_ia32_extract128i256 ((__v4di)(__m256i)(X), (int)(M))) +#endif + +#define _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI16(op) \ + __v8hi __T1 = (__v8hi)_mm256_avx512_extracti128_si256 (__W, 0); \ + __v8hi __T2 = (__v8hi)_mm256_avx512_extracti128_si256 (__W, 1); \ + __v8hi __T3 = __T1 op __T2; \ + __v8hi __T4 = __builtin_shufflevector (__T3, __T3, 4, 5, 6, 7, 4, 5, 6, 7); \ + __v8hi __T5 = __T3 op __T4; \ + __v8hi __T6 = __builtin_shufflevector (__T5, __T5, 2, 3, 2, 3, 4, 5, 6, 7); \ + __v8hi __T7 = __T5 op __T6; \ + __v8hi __T8 = __builtin_shufflevector (__T7, __T7, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T9 = __T7 op __T8; \ + return __T9[0] + +#define _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP16(op) \ + __m128i __T1 = _mm256_avx512_extracti128_si256 (__V, 0); \ + __m128i __T2 = _mm256_avx512_extracti128_si256 (__V, 1); \ + __m128i __T3 = _mm_avx512_##op (__T1, __T2); \ + __m128i __T4 = (__m128i)__builtin_shufflevector ((__v8hi)__T3, \ + (__v8hi)__T3, 4, 5, 6, 7, 4, 5, 6, 7); \ + __m128i __T5 = _mm_avx512_##op (__T3, __T4); \ + __m128i __T6 = (__m128i)__builtin_shufflevector ((__v8hi)__T5, \ + (__v8hi)__T5, 2, 3, 2, 3, 4, 5, 6, 7); \ + __m128i __T7 = _mm_avx512_##op (__T5, __T6); \ + __m128i __T8 = (__m128i)__builtin_shufflevector ((__v8hi)__T7, \ + (__v8hi)__T7, 1, 1, 2, 3, 4, 5, 6, 7); \ + __v8hi __T9 = (__v8hi)_mm_avx512_##op (__T7, __T8); \ + return __T9[0] + +#define _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI8(op) \ + __v16qi __T1 = (__v16qi)_mm256_avx512_extracti128_si256 (__W, 0); \ + __v16qi __T2 = (__v16qi)_mm256_avx512_extracti128_si256 (__W, 1); \ + __v16qi __T3 = __T1 op __T2; \ + __v16qi __T4 = __builtin_shufflevector (__T3, __T3, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T5 = __T3 op __T4; \ + __v16qi __T6 = __builtin_shufflevector (__T5, __T5, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T7 = __T5 op __T6; \ + __v16qi __T8 = __builtin_shufflevector (__T7, __T7, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T9 = __T7 op __T8; \ + __v16qi __T10 = __builtin_shufflevector (__T9, __T9, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T11 = __T9 op __T10; \ + return __T11[0] + +#define _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP8(op) \ + __m128i __T1 = _mm256_avx512_extracti128_si256 (__V, 0); \ + __m128i __T2 = _mm256_avx512_extracti128_si256 (__V, 1); \ + __m128i __T3 = _mm_avx512_##op (__T1, __T2); \ + __m128i __T4 = (__m128i)__builtin_shufflevector ((__v16qi)__T3, \ + (__v16qi)__T3, \ + 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T5 = _mm_avx512_##op (__T3, __T4); \ + __m128i __T6 = (__m128i)__builtin_shufflevector ((__v16qi)__T5, \ + (__v16qi)__T5, \ + 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T7 = _mm_avx512_##op (__T5, __T6); \ + __m128i __T8 = (__m128i)__builtin_shufflevector ((__v16qi)__T7, \ + (__v16qi)__T5, \ + 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __m128i __T9 = _mm_avx512_##op (__T7, __T8); \ + __m128i __T10 = (__m128i)__builtin_shufflevector ((__v16qi)__T9, \ + (__v16qi)__T9, \ + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + __v16qi __T11 = (__v16qi)_mm_avx512_##op (__T9, __T10); \ + return __T11[0] + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdquqi256_mask ((__v32qi) __A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_epi8 (__m128i __W, __mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdquqi128_mask ((__v16qi) __A, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_epi8 (__mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdquqi128_mask ((__v16qi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi8 (void *__P, __m256i __A) +{ + *(__v32qi_u *) __P = (__v32qi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A) +{ + __builtin_ia32_storedquqi256_mask ((char *) __P, + (__v32qi) __A, + (__mmask32) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi8 (void *__P, __m128i __A) +{ + *(__v16qi_u *) __P = (__v16qi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A) +{ + __builtin_ia32_storedquqi128_mask ((char *) __P, + (__v16qi) __A, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_epi16 (void const *__P) +{ + return (__m256i) (*(__v16hi_u *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddquhi256_mask ((const short *) __P, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddquhi256_mask ((const short *) __P, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_epi16 (void const *__P) +{ + return (__m128i) (*(__v8hi_u *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddquhi128_mask ((const short *) __P, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_epi16 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddquhi128_mask ((const short *) __P, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_epi16 (__m256i __W, __mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdquhi256_mask ((__v16hi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_epi16 (__mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdquhi256_mask ((__v16hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdquhi128_mask ((__v8hi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_epi16 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdquhi128_mask ((__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_epi8 (void const *__P) +{ + return (__m256i) (*(__v32qi_u *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddquqi256_mask ((const char *) __P, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddquqi256_mask ((const char *) __P, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_epi8 (void const *__P) +{ + return (__m128i) (*(__v16qi_u *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddquqi128_mask ((const char *) __P, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddquqi128_mask ((const char *) __P, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W) +{ + return (__m128i) __builtin_ia32_blendmw_128_mask ((__v8hi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W) +{ + return (__m128i) __builtin_ia32_blendmb_128_mask ((__v16qi) __A, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W) +{ + return (__m256i) __builtin_ia32_blendmw_256_mask ((__v16hi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W) +{ + return (__m256i) __builtin_ia32_blendmb_256_mask ((__v32qi) __A, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi16_epi8 (__m256i __A) +{ + + return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi16_storeu_epi8 (void * __P, __mmask16 __M,__m256i __A) +{ + __builtin_ia32_pmovwb256mem_mask ((__v16qi *) __P , (__v16hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi16_epi8 (__mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi16_epi8 (__m128i __A) +{ + + return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask8 __M,__m128i __A) +{ + __builtin_ia32_pmovswb128mem_mask ((unsigned long long *) __P , (__v8hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi16_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi16_epi8 (__m256i __A) +{ + + return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask16 __M,__m256i __A) +{ + __builtin_ia32_pmovswb256mem_mask ((__v16qi *) __P , (__v16hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi16_epi8 (__mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi16_epi8 (__m128i __A) +{ + + return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M,__m128i __A) +{ + __builtin_ia32_pmovuswb128mem_mask ((unsigned long long *) __P , (__v8hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi16_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi16_epi8 (__m256i __A) +{ + + return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask16 __M,__m256i __A) +{ + __builtin_ia32_pmovuswb256mem_mask ((__v16qi *) __P , (__v16hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi16_epi8 (__mmask16 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastb_epi8 (__m256i __O, __mmask32 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastb256_mask ((__v16qi) __A, + (__v32qi) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastb_epi8 (__mmask32 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastb256_mask ((__v16qi) __A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A) +{ + return (__m256i) __builtin_ia32_pbroadcastb256_gpr_mask (__A, + (__v32qi) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_set1_epi8 (__mmask32 __M, char __A) +{ + return (__m256i) __builtin_ia32_pbroadcastb256_gpr_mask (__A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcastb_epi8 (__m128i __O, __mmask16 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastb128_mask ((__v16qi) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcastb_epi8 (__mmask16 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastb128_mask ((__v16qi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A) +{ + return (__m128i) __builtin_ia32_pbroadcastb128_gpr_mask (__A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_set1_epi8 (__mmask16 __M, char __A) +{ + return (__m128i) __builtin_ia32_pbroadcastb128_gpr_mask (__A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastw_epi16 (__m256i __O, __mmask16 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastw256_mask ((__v8hi) __A, + (__v16hi) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastw256_mask ((__v8hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A) +{ + return (__m256i) __builtin_ia32_pbroadcastw256_gpr_mask (__A, + (__v16hi) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_set1_epi16 (__mmask16 __M, short __A) +{ + return (__m256i) __builtin_ia32_pbroadcastw256_gpr_mask (__A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcastw_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastw128_mask ((__v8hi) __A, + (__v8hi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcastw_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastw128_mask ((__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A) +{ + return (__m128i) __builtin_ia32_pbroadcastw128_gpr_mask (__A, + (__v8hi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_set1_epi16 (__mmask8 __M, short __A) +{ + return (__m128i) __builtin_ia32_pbroadcastw128_gpr_mask (__A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B, + (__v16hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_epi16 (__mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B, + (__v16hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_permvarhi256_mask ((__v16hi) __B, + (__v16hi) __A, + (__v16hi) __W, + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutexvar_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B, + (__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutexvar_epi16 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B, + (__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutexvar_epi16 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_permvarhi128_mask ((__v8hi) __B, + (__v8hi) __A, + (__v8hi) __W, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_epi16 (__m256i __A, __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I + /* idx */ , + (__v16hi) __A, + (__v16hi) __B, + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_epi16 (__m256i __A, __mmask16 __U, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I + /* idx */ , + (__v16hi) __A, + (__v16hi) __B, + (__mmask16) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_epi16 (__m256i __A, __m256i __I, + __mmask16 __U, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A, + (__v16hi) __I + /* idx */ , + (__v16hi) __B, + (__mmask16) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varhi256_maskz ((__v16hi) __I + /* idx */ , + (__v16hi) __A, + (__v16hi) __B, + (__mmask16) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_epi16 (__m128i __A, __m128i __I, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I + /* idx */ , + (__v8hi) __A, + (__v8hi) __B, + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_epi16 (__m128i __A, __mmask8 __U, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I + /* idx */ , + (__v8hi) __A, + (__v8hi) __B, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_epi16 (__m128i __A, __m128i __I, __mmask8 __U, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A, + (__v8hi) __I + /* idx */ , + (__v8hi) __B, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varhi128_maskz ((__v8hi) __I + /* idx */ , + (__v8hi) __A, + (__v8hi) __B, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_maddubs_epi16 (__m256i __W, __mmask16 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X, + (__v32qi) __Y, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_maddubs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X, + (__v32qi) __Y, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_maddubs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X, + (__v16qi) __Y, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_maddubs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X, + (__v16qi) __Y, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_madd_epi16 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_madd_epi16 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_madd_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_madd_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movepi8_mask (__m128i __A) +{ + return (__mmask16) __builtin_ia32_cvtb2mask128 ((__v16qi) __A); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movepi8_mask (__m256i __A) +{ + return (__mmask32) __builtin_ia32_cvtb2mask256 ((__v32qi) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movepi16_mask (__m128i __A) +{ + return (__mmask8) __builtin_ia32_cvtw2mask128 ((__v8hi) __A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movepi16_mask (__m256i __A) +{ + return (__mmask16) __builtin_ia32_cvtw2mask256 ((__v16hi) __A); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movm_epi8 (__mmask16 __A) +{ + return (__m128i) __builtin_ia32_cvtmask2b128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movm_epi8 (__mmask32 __A) +{ + return (__m256i) __builtin_ia32_cvtmask2b256 (__A); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movm_epi16 (__mmask8 __A) +{ + return (__m128i) __builtin_ia32_cvtmask2w128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movm_epi16 (__mmask16 __A) +{ + return (__m256i) __builtin_ia32_cvtmask2w256 (__A); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_test_epi8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ptestmb128 ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_test_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ptestmb128 ((__v16qi) __A, + (__v16qi) __B, __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_test_epi8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ptestmb256 ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_test_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ptestmb256 ((__v32qi) __A, + (__v32qi) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_test_epi16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmw128 ((__v8hi) __A, + (__v8hi) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_test_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmw128 ((__v8hi) __A, + (__v8hi) __B, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_test_epi16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ptestmw256 ((__v16hi) __A, + (__v16hi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_test_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ptestmw256 ((__v16hi) __A, + (__v16hi) __B, __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epu16 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epu16 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epu16 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epu16 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epi16 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epi16 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epu8 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epu8 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epu8 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epi8 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epi8 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epi8 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epi8 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epu8 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epu8 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epu8 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epi8 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epi8 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epi8 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epi8 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epi16 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epi16 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epi16 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epi16 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epu16 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epu16 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epu16 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epu16 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epi16 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epi16 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __M); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_alignr_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B, const int __N) +{ + return (__m256i) __builtin_ia32_palignr256_mask ((__v4di) __A, + (__v4di) __B, + __N * 8, + (__v4di) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_alignr_epi8 (__mmask32 __U, __m256i __A, __m256i __B, + const int __N) +{ + return (__m256i) __builtin_ia32_palignr256_mask ((__v4di) __A, + (__v4di) __B, + __N * 8, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_alignr_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B, const int __N) +{ + return (__m128i) __builtin_ia32_palignr128_mask ((__v2di) __A, + (__v2di) __B, + __N * 8, + (__v2di) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_alignr_epi8 (__mmask16 __U, __m128i __A, __m128i __B, + const int __N) +{ + return (__m128i) __builtin_ia32_palignr128_mask ((__v2di) __A, + (__v2di) __B, + __N * 8, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dbsad_epu8 (__m256i __A, __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi) __A, + (__v32qi) __B, + __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dbsad_epu8 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi) __A, + (__v32qi) __B, + __imm, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dbsad_epu8 (__mmask16 __U, __m256i __A, __m256i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi) __A, + (__v32qi) __B, + __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dbsad_epu8 (__m128i __A, __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi) __A, + (__v16qi) __B, + __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dbsad_epu8 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi) __A, + (__v16qi) __B, + __imm, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dbsad_epu8 (__mmask8 __U, __m128i __A, __m128i __B, + const int __imm) +{ + return (__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi) __A, + (__v16qi) __B, + __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epi16_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epi16_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epi16_mask (__mmask16 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epi16_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epi8_mask (__mmask16 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epi8_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epi8_mask (__mmask32 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, __P, + (__mmask32) __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epi8_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, __P, + (__mmask32) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epu16_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epu16_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epu16_mask (__mmask16 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epu16_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epu8_mask (__mmask16 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, __P, + (__mmask16) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epu8_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, __P, + (__mmask16) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epu8_mask (__mmask32 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, __P, + (__mmask32) __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epu8_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, __P, + (__mmask32) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srli_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_psrlwi256_mask ((__v16hi) __A, __imm, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srli_epi16 (__mmask16 __U, __m256i __A, const int __imm) +{ + return (__m256i) __builtin_ia32_psrlwi256_mask ((__v16hi) __A, __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srli_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_psrlwi128_mask ((__v8hi) __A, __imm, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_psrlwi128_mask ((__v8hi) __A, __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shufflehi_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_pshufhw256_mask ((__v16hi) __A, + __imm, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shufflehi_epi16 (__mmask16 __U, __m256i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_pshufhw256_mask ((__v16hi) __A, + __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shufflehi_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_pshufhw128_mask ((__v8hi) __A, __imm, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shufflehi_epi16 (__mmask8 __U, __m128i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_pshufhw128_mask ((__v8hi) __A, __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shufflelo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_pshuflw256_mask ((__v16hi) __A, + __imm, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shufflelo_epi16 (__mmask16 __U, __m256i __A, + const int __imm) +{ + return (__m256i) __builtin_ia32_pshuflw256_mask ((__v16hi) __A, + __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shufflelo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_pshuflw128_mask ((__v8hi) __A, __imm, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shufflelo_epi16 (__mmask8 __U, __m128i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_pshuflw128_mask ((__v8hi) __A, __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srai_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrawi256_mask ((__v16hi) __A, __imm, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srai_epi16 (__mmask16 __U, __m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrawi256_mask ((__v16hi) __A, __imm, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srai_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrawi128_mask ((__v8hi) __A, __imm, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srai_epi16 (__mmask8 __U, __m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrawi128_mask ((__v8hi) __A, __imm, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_slli_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + unsigned int __B) +{ + return (__m256i) __builtin_ia32_psllwi256_mask ((__v16hi) __A, __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_slli_epi16 (__mmask16 __U, __m256i __A, unsigned int __B) +{ + return (__m256i) __builtin_ia32_psllwi256_mask ((__v16hi) __A, __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_slli_epi16 (__m128i __W, __mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_psllwi128_mask ((__v8hi) __A, __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_psllwi128_mask ((__v8hi) __A, __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +#else +#define _mm256_mask_alignr_epi8(W, U, X, Y, N) \ + ((__m256i) __builtin_ia32_palignr256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)((N) * 8), \ + (__v4di)(__m256i)(W), (__mmask32)(U))) + +#define _mm256_mask_srli_epi16(W, U, A, B) \ + ((__m256i) __builtin_ia32_psrlwi256_mask ((__v16hi)(__m256i)(A), \ + (int)(B), (__v16hi)(__m256i)(W), (__mmask16)(U))) + +#define _mm256_maskz_srli_epi16(U, A, B) \ + ((__m256i) __builtin_ia32_psrlwi256_mask ((__v16hi)(__m256i)(A), \ + (int)(B), (__v16hi)_mm256_avx512_setzero_si256 (), (__mmask16)(U))) + +#define _mm_mask_srli_epi16(W, U, A, B) \ + ((__m128i) __builtin_ia32_psrlwi128_mask ((__v8hi)(__m128i)(A), \ + (int)(B), (__v8hi)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srli_epi16(U, A, B) \ + ((__m128i) __builtin_ia32_psrlwi128_mask ((__v8hi)(__m128i)(A), \ + (int)(B), (__v8hi)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_mask_srai_epi16(W, U, A, B) \ + ((__m256i) __builtin_ia32_psrawi256_mask ((__v16hi)(__m256i)(A), \ + (unsigned int)(B), (__v16hi)(__m256i)(W), (__mmask16)(U))) + +#define _mm256_maskz_srai_epi16(U, A, B) \ + ((__m256i) __builtin_ia32_psrawi256_mask ((__v16hi)(__m256i)(A), \ + (unsigned int)(B), (__v16hi)_mm256_avx512_setzero_si256 (), (__mmask16)(U))) + +#define _mm_mask_srai_epi16(W, U, A, B) \ + ((__m128i) __builtin_ia32_psrawi128_mask ((__v8hi)(__m128i)(A), \ + (unsigned int)(B), (__v8hi)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srai_epi16(U, A, B) \ + ((__m128i) __builtin_ia32_psrawi128_mask ((__v8hi)(__m128i)(A), \ + (unsigned int)(B), (__v8hi)_mm_avx512_setzero_si128(), (__mmask8)(U))) + +#define _mm256_mask_shufflehi_epi16(W, U, A, B) \ + ((__m256i) __builtin_ia32_pshufhw256_mask ((__v16hi)(__m256i)(A), (int)(B), \ + (__v16hi)(__m256i)(W), \ + (__mmask16)(U))) + +#define _mm256_maskz_shufflehi_epi16(U, A, B) \ + ((__m256i) __builtin_ia32_pshufhw256_mask ((__v16hi)(__m256i)(A), (int)(B), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask16)(U))) + +#define _mm_mask_shufflehi_epi16(W, U, A, B) \ + ((__m128i) __builtin_ia32_pshufhw128_mask ((__v8hi)(__m128i)(A), (int)(B), \ + (__v8hi)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_shufflehi_epi16(U, A, B) \ + ((__m128i) __builtin_ia32_pshufhw128_mask ((__v8hi)(__m128i)(A), (int)(B), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm256_mask_shufflelo_epi16(W, U, A, B) \ + ((__m256i) __builtin_ia32_pshuflw256_mask ((__v16hi)(__m256i)(A), (int)(B), \ + (__v16hi)(__m256i)(W), \ + (__mmask16)(U))) + +#define _mm256_maskz_shufflelo_epi16(U, A, B) \ + ((__m256i) __builtin_ia32_pshuflw256_mask ((__v16hi)(__m256i)(A), (int)(B), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask16)(U))) + +#define _mm_mask_shufflelo_epi16(W, U, A, B) \ + ((__m128i) __builtin_ia32_pshuflw128_mask ((__v8hi)(__m128i)(A), (int)(B), \ + (__v8hi)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_shufflelo_epi16(U, A, B) \ + ((__m128i) __builtin_ia32_pshuflw128_mask ((__v8hi)(__m128i)(A), (int)(B), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm256_maskz_alignr_epi8(U, X, Y, N) \ + ((__m256i) __builtin_ia32_palignr256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)((N) * 8), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask32)(U))) + +#define _mm_mask_alignr_epi8(W, U, X, Y, N) \ + ((__m128i) __builtin_ia32_palignr128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)((N) * 8), \ + (__v2di)(__m128i)(W), (__mmask16)(U))) + +#define _mm_maskz_alignr_epi8(U, X, Y, N) \ + ((__m128i) __builtin_ia32_palignr128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)((N) * 8), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask16)(U))) + +#define _mm_mask_slli_epi16(W, U, X, C) \ + ((__m128i)__builtin_ia32_psllwi128_mask ((__v8hi)(__m128i)(X), \ + (unsigned int)(C), \ + (__v8hi)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_slli_epi16(U, X, C) \ + ((__m128i)__builtin_ia32_psllwi128_mask ((__v8hi)(__m128i)(X), \ + (unsigned int)(C), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm256_dbsad_epu8(X, Y, C) \ + ((__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi)(__m256i) (X), \ + (__v32qi)(__m256i) (Y), (int) (C), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256(),\ + (__mmask16)-1)) + +#define _mm256_mask_slli_epi16(W, U, X, C) \ + ((__m256i)__builtin_ia32_psllwi256_mask ((__v16hi)(__m256i)(X), \ + (unsigned int)(C), \ + (__v16hi)(__m256i)(W), \ + (__mmask16)(U))) + +#define _mm256_maskz_slli_epi16(U, X, C) \ + ((__m256i)__builtin_ia32_psllwi256_mask ((__v16hi)(__m256i)(X), \ + (unsigned int)(C), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask16)(U))) + +#define _mm256_mask_dbsad_epu8(W, U, X, Y, C) \ + ((__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi)(__m256i) (X), \ + (__v32qi)(__m256i) (Y), (int) (C), \ + (__v16hi)(__m256i)(W), \ + (__mmask16)(U))) + +#define _mm256_maskz_dbsad_epu8(U, X, Y, C) \ + ((__m256i) __builtin_ia32_dbpsadbw256_mask ((__v32qi)(__m256i) (X), \ + (__v32qi)(__m256i) (Y), (int) (C), \ + (__v16hi)(__m256i)_mm256_avx512_setzero_si256(),\ + (__mmask16)(U))) + +#define _mm_dbsad_epu8(X, Y, C) \ + ((__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi)(__m128i) (X), \ + (__v16qi)(__m128i) (Y), (int) (C), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128(), \ + (__mmask8)-1)) + +#define _mm_mask_dbsad_epu8(W, U, X, Y, C) \ + ((__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi)(__m128i) (X), \ + (__v16qi)(__m128i) (Y), (int) (C), \ + (__v8hi)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_dbsad_epu8(U, X, Y, C) \ + ((__m128i) __builtin_ia32_dbpsadbw128_mask ((__v16qi)(__m128i) (X), \ + (__v16qi)(__m128i) (Y), (int) (C), \ + (__v8hi)(__m128i)_mm_avx512_setzero_si128(), \ + (__mmask8)(U))) + +#define _mm_cmp_epi16_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi)(__m128i)(X), \ + (__v8hi)(__m128i)(Y), (int)(P),\ + (__mmask8)(-1))) + +#define _mm_cmp_epi8_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(P),\ + (__mmask16)(-1))) + +#define _mm256_cmp_epi16_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi)(__m256i)(X), \ + (__v16hi)(__m256i)(Y), (int)(P),\ + (__mmask16)(-1))) + +#define _mm256_cmp_epi8_mask(X, Y, P) \ + ((__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi)(__m256i)(X), \ + (__v32qi)(__m256i)(Y), (int)(P),\ + (__mmask32)(-1))) + +#define _mm_cmp_epu16_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi)(__m128i)(X), \ + (__v8hi)(__m128i)(Y), (int)(P),\ + (__mmask8)(-1))) + +#define _mm_cmp_epu8_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(P),\ + (__mmask16)(-1))) + +#define _mm256_cmp_epu16_mask(X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi)(__m256i)(X), \ + (__v16hi)(__m256i)(Y), (int)(P),\ + (__mmask16)(-1))) + +#define _mm256_cmp_epu8_mask(X, Y, P) \ + ((__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi)(__m256i)(X), \ + (__v32qi)(__m256i)(Y), (int)(P),\ + (__mmask32)-1)) + +#define _mm_mask_cmp_epi16_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi)(__m128i)(X), \ + (__v8hi)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_epi8_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(P),\ + (__mmask16)(M))) + +#define _mm256_mask_cmp_epi16_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi)(__m256i)(X), \ + (__v16hi)(__m256i)(Y), (int)(P),\ + (__mmask16)(M))) + +#define _mm256_mask_cmp_epi8_mask(M, X, Y, P) \ + ((__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi)(__m256i)(X), \ + (__v32qi)(__m256i)(Y), (int)(P),\ + (__mmask32)(M))) + +#define _mm_mask_cmp_epu16_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi)(__m128i)(X), \ + (__v8hi)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_epu8_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(P),\ + (__mmask16)(M))) + +#define _mm256_mask_cmp_epu16_mask(M, X, Y, P) \ + ((__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi)(__m256i)(X), \ + (__v16hi)(__m256i)(Y), (int)(P),\ + (__mmask16)(M))) + +#define _mm256_mask_cmp_epu8_mask(M, X, Y, P) \ + ((__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi)(__m256i)(X), \ + (__v32qi)(__m256i)(Y), (int)(P),\ + (__mmask32)(M))) +#endif + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epi8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 4, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epi8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 1, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epi8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 5, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epi8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 2, + (__mmask32) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epi16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epi16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epi16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epi16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 2, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epu8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epu8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epu8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epu8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 2, + (__mmask16) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epu16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epu16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epu16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epu16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epi8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epi8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epi8_mask (__m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 2, + (__mmask16) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epi16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epi16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epi16_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 2, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mulhrs_epi16 (__m256i __W, __mmask16 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X, + (__v16hi) __Y, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mulhrs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X, + (__v16hi) __Y, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mulhi_epu16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mulhi_epu16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mulhi_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mulhi_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mulhi_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mulhi_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mulhi_epu16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mulhi_epu16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mulhrs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X, + (__v8hi) __Y, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mulhrs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X, + (__v8hi) __Y, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mullo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mullo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mullo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mullo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi8_epi16 (__m256i __W, __mmask16 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbw256_mask ((__v16qi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi8_epi16 (__mmask16 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbw256_mask ((__v16qi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi8_epi16 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbw128_mask ((__v16qi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi8_epi16 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbw128_mask ((__v16qi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu8_epi16 (__m256i __W, __mmask16 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbw256_mask ((__v16qi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbw256_mask ((__v16qi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu8_epi16 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbw128_mask ((__v16qi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu8_epi16 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbw128_mask ((__v16qi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_avg_epu8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_avg_epu8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_avg_epu8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_avg_epu8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_avg_epu16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_avg_epu16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_avg_epu16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_avg_epu16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_adds_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_adds_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_adds_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_adds_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_adds_epu8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_adds_epu8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_adds_epu16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_adds_epu16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_subs_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_subs_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_subs_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_subs_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_subs_epu8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_subs_epu8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_subs_epu16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_subs_epu16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhbw256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhbw256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhbw128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhbw128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklbw256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklbw256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklbw128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklbw128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklwd256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklwd128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epu8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __A, + (__v16qi) __B, 0, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epu8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __A, + (__v16qi) __B, 0, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqb128_mask ((__v16qi) __A, + (__v16qi) __B, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epu8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __A, + (__v32qi) __B, 0, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_pcmpeqb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epu8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __A, + (__v32qi) __B, 0, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_pcmpeqb256_mask ((__v32qi) __A, + (__v32qi) __B, + __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epu16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __A, + (__v8hi) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epu16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __A, + (__v8hi) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqw128_mask ((__v8hi) __A, + (__v8hi) __B, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epu16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __A, + (__v16hi) __B, 0, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epu16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __A, + (__v16hi) __B, 0, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_pcmpeqw256_mask ((__v16hi) __A, + (__v16hi) __B, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epu8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __A, + (__v16qi) __B, 6, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epu8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __A, + (__v16qi) __B, 6, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtb128_mask ((__v16qi) __A, + (__v16qi) __B, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epu8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __A, + (__v32qi) __B, 6, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_pcmpgtb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epu8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __A, + (__v32qi) __B, 6, + __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_pcmpgtb256_mask ((__v32qi) __A, + (__v32qi) __B, + __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epu16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __A, + (__v8hi) __B, 6, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epu16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __A, + (__v8hi) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtw128_mask ((__v8hi) __A, + (__v8hi) __B, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epu16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __A, + (__v16hi) __B, 6, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtw256_mask ((__v16hi) __A, + (__v16hi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epu16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __A, + (__v16hi) __B, 6, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_pcmpgtw256_mask ((__v16hi) __A, + (__v16hi) __B, + __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testn_epi8_mask (__m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmb128 ((__v16qi) __A, + (__v16qi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_testn_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmb128 ((__v16qi) __A, + (__v16qi) __B, __U); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testn_epi8_mask (__m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ptestnmb256 ((__v32qi) __A, + (__v32qi) __B, + (__mmask32) -1); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_testn_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__mmask32) __builtin_ia32_ptestnmb256 ((__v32qi) __A, + (__v32qi) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testn_epi16_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmw128 ((__v8hi) __A, + (__v8hi) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_testn_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmw128 ((__v8hi) __A, + (__v8hi) __B, __U); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testn_epi16_mask (__m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmw256 ((__v16hi) __A, + (__v16hi) __B, + (__mmask16) -1); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_testn_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__mmask16) __builtin_ia32_ptestnmw256 ((__v16hi) __A, + (__v16hi) __B, __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_epi8 (__m256i __W, __mmask32 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_epi8 (__mmask32 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A, + (__v32qi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shuffle_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shuffle_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_packs_epi16 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_packs_epi16 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v32qi) __W, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_packs_epi16 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_packs_epi16 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v16qi) __W, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_packus_epi16 (__mmask32 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v32qi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_packus_epi16 (__m256i __W, __mmask32 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A, + (__v16hi) __B, + (__v32qi) __W, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_packus_epi16 (__mmask16 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_packus_epi16 (__m128i __W, __mmask16 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v16qi) __W, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_abs_epi8 (__m256i __W, __mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A, + (__v32qi) __W, + (__mmask32) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A, + (__v32qi) + _mm256_avx512_setzero_si256 (), + (__mmask32) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_abs_epi8 (__m128i __W, __mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_abs_epi8 (__mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_abs_epi16 (__m256i __W, __mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_abs_epi16 (__mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_abs_epi16 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_abs_epi16 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epu8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 4, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epu8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 1, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epu8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 5, + (__mmask32) -1); +} + +extern __inline __mmask32 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epu8_mask (__m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 2, + (__mmask32) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epu16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 4, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epu16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 1, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epu16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 5, + (__mmask16) -1); +} + +extern __inline __mmask16 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epu16_mask (__m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 2, + (__mmask16) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi16 (void *__P, __m256i __A) +{ + *(__v16hi_u *) __P = (__v16hi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A) +{ + __builtin_ia32_storedquhi256_mask ((short *) __P, + (__v16hi) __A, + (__mmask16) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi16 (void *__P, __m128i __A) +{ + *(__v8hi_u *) __P = (__v8hi_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_storedquhi128_mask ((short *) __P, + (__v8hi) __A, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_adds_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_subs_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_subs_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_subs_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_subs_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_subs_epu8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_subs_epu8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_subs_epu16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_subs_epu16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srl_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psrlw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srl_epi16 (__mmask16 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psrlw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srl_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sra_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psraw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sra_epi16 (__mmask16 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psraw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sra_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psraw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sra_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psraw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_adds_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_adds_epu8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_adds_epu8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_adds_epu16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_adds_epu16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_adds_epi8 (__m128i __W, __mmask16 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_adds_epi8 (__mmask16 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A, + (__v16qi) __B, + (__v16qi) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi16_epi8 (__m128i __A) +{ + + return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, + (__v16qi)_mm_avx512_undefined_si128(), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi16_storeu_epi8 (void * __P, __mmask8 __M,__m128i __A) +{ + __builtin_ia32_pmovwb128mem_mask ((unsigned long long *) __P , (__v8hi) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi16_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srav_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srav_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srav_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srav_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srav_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srav_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srlv_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srlv_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srlv_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srlv_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srlv_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srlv_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sllv_epi16 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sllv_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sllv_epi16 (__mmask16 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A, + (__v16hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sllv_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sllv_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sllv_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sll_epi16 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psllw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psllw128_mask ((__v8hi) __A, + (__v8hi) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sll_epi16 (__m256i __W, __mmask16 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psllw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sll_epi16 (__mmask16 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psllw256_mask ((__v16hi) __A, + (__v8hi) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_packus_epi32 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A, + (__v8si) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_packus_epi32 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A, + (__v8si) __B, + (__v16hi) __W, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_packus_epi32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A, + (__v4si) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_packus_epi32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A, + (__v4si) __B, + (__v8hi) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_packs_epi32 (__mmask16 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A, + (__v8si) __B, + (__v16hi) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_packs_epi32 (__m256i __W, __mmask16 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A, + (__v8si) __B, + (__v16hi) __W, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_packs_epi32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A, + (__v4si) __B, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_packs_epi32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A, + (__v4si) __B, + (__v8hi) __W, __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epu8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epu8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epu8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epu8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 2, + (__mmask16) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epu16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epu16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epu16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epu16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epi8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epi8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epi8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epi8_mask (__mmask16 __M, __m128i __X, __m128i __Y) +{ + return (__mmask16) __builtin_ia32_cmpb128_mask ((__v16qi) __X, + (__v16qi) __Y, 2, + (__mmask16) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epi16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epi16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epi16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epi16_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpw128_mask ((__v8hi) __X, + (__v8hi) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epu8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 4, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epu8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 1, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epu8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 5, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epu8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_ucmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 2, + (__mmask32) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epu16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epu16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epu16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epu16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_ucmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 2, + (__mmask16) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epi8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 4, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epi8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 1, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epi8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 5, + (__mmask32) __M); +} + +extern __inline __mmask32 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epi8_mask (__mmask32 __M, __m256i __X, __m256i __Y) +{ + return (__mmask32) __builtin_ia32_cmpb256_mask ((__v32qi) __X, + (__v32qi) __Y, 2, + (__mmask32) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epi16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 4, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epi16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 1, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epi16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 5, + (__mmask16) __M); +} + +extern __inline __mmask16 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epi16_mask (__mmask16 __M, __m256i __X, __m256i __Y) +{ + return (__mmask16) __builtin_ia32_cmpw256_mask ((__v16hi) __X, + (__v16hi) __Y, 2, + (__mmask16) __M); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_add_epi16 (__mmask8 __M, __m128i __W) +{ + __W = _mm_maskz_mov_epi16 (__M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI16 (+); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_mul_epi16 (__mmask8 __M, __m128i __W) +{ + __W = _mm_mask_mov_epi16 (_mm_avx512_set1_epi16 (1), __M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI16 (*); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_and_epi16 (__mmask8 __M, __m128i __W) +{ + __W = _mm_mask_mov_epi16 (_mm_avx512_set1_epi16 (-1), __M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI16 (&); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_or_epi16 (__mmask8 __M, __m128i __W) +{ + __W = _mm_maskz_mov_epi16 (__M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI16 (|); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_max_epi16 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi16 (_mm_avx512_set1_epi16 (-32767-1), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (avx512_max_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_max_epu16 (__mmask16 __M, __m128i __V) +{ + __V = _mm_maskz_mov_epi16 (__M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (avx512_max_epu16); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_min_epi16 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi16 (_mm_avx512_set1_epi16 (32767), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (avx512_min_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_min_epu16 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi16 (_mm_avx512_set1_epi16 (-1), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP16 (avx512_min_epu16); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_add_epi16 (__mmask16 __M, __m256i __W) +{ + __W = _mm256_maskz_mov_epi16 (__M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI16 (+); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_mul_epi16 (__mmask16 __M, __m256i __W) +{ + __W = _mm256_mask_mov_epi16 (_mm256_avx512_set1_epi16 (1), __M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI16 (*); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_and_epi16 (__mmask16 __M, __m256i __W) +{ + __W = _mm256_mask_mov_epi16 (_mm256_avx512_set1_epi16 (-1), __M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI16 (&); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_or_epi16 (__mmask16 __M, __m256i __W) +{ + __W = _mm256_maskz_mov_epi16 (__M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI16 (|); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_max_epi16 (__mmask16 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi16 (_mm256_avx512_set1_epi16 (-32767-1), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_max_epu16 (__mmask16 __M, __m256i __V) +{ + __V = _mm256_maskz_mov_epi16 (__M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP16 (max_epu16); +} + +extern __inline short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_min_epi16 (__mmask16 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi16 (_mm256_avx512_set1_epi16 (32767), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epi16); +} + +extern __inline unsigned short +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_min_epu16 (__mmask16 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi16 (_mm256_avx512_set1_epi16 (-1), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP16 (min_epu16); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_add_epi8 (__mmask16 __M, __m128i __W) +{ + __W = _mm_maskz_mov_epi8 (__M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI8 (+); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_mul_epi8 (__mmask16 __M, __m128i __W) +{ + __W = _mm_mask_mov_epi8 (_mm_avx512_set1_epi8 (1), __M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI8 (*); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_and_epi8 (__mmask16 __M, __m128i __W) +{ + __W = _mm_mask_mov_epi8 (_mm_avx512_set1_epi8 (-1), __M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI8 (&); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_or_epi8 (__mmask16 __M, __m128i __W) +{ + __W = _mm_maskz_mov_epi8 (__M, __W); + _MM_REDUCE_OPERATOR_BASIC_EPI8 (|); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_max_epi8 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi8 (_mm_avx512_set1_epi8 (-127-1), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (avx512_max_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_max_epu8 (__mmask16 __M, __m128i __V) +{ + __V = _mm_maskz_mov_epi8 (__M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (avx512_max_epu8); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_min_epi8 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi8 (_mm_avx512_set1_epi8 (127), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (avx512_min_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_min_epu8 (__mmask16 __M, __m128i __V) +{ + __V = _mm_mask_mov_epi8 (_mm_avx512_set1_epi8 (-1), __M, __V); + _MM_REDUCE_OPERATOR_MAX_MIN_EP8 (avx512_min_epu8); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_add_epi8 (__mmask32 __M, __m256i __W) +{ + __W = _mm256_maskz_mov_epi8 (__M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI8 (+); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_mul_epi8 (__mmask32 __M, __m256i __W) +{ + __W = _mm256_mask_mov_epi8 (_mm256_avx512_set1_epi8 (1), __M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI8 (*); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_and_epi8 (__mmask32 __M, __m256i __W) +{ + __W = _mm256_mask_mov_epi8 (_mm256_avx512_set1_epi8 (-1), __M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI8 (&); +} + +extern __inline char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_or_epi8 (__mmask32 __M, __m256i __W) +{ + __W = _mm256_maskz_mov_epi8 (__M, __W); + _MM256_AVX512_REDUCE_OPERATOR_BASIC_EPI8 (|); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_max_epi8 (__mmask32 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi8 (_mm256_avx512_set1_epi8 (-127-1), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_max_epu8 (__mmask32 __M, __m256i __V) +{ + __V = _mm256_maskz_mov_epi8 (__M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP8 (max_epu8); +} + +extern __inline signed char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_min_epi8 (__mmask32 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi8 (_mm256_avx512_set1_epi8 (127), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epi8); +} + +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_min_epu8 (__mmask32 __M, __m256i __V) +{ + __V = _mm256_mask_mov_epi8 (_mm256_avx512_set1_epi8 (-1), __M, __V); + _MM256_AVX512_REDUCE_OPERATOR_MAX_MIN_EP8 (min_epu8); +} + +#ifdef __DISABLE_AVX512VLBW__ +#undef __DISABLE_AVX512VLBW__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VLBW__ */ + +#endif /* _AVX512VLBWINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vldqintrin.h b/template/sysroot/include/avx512vldqintrin.h new file mode 100644 index 0000000..eb2b63d --- /dev/null +++ b/template/sysroot/include/avx512vldqintrin.h @@ -0,0 +1,2016 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VLDQINTRIN_H_INCLUDED +#define _AVX512VLDQINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512DQ__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vl,avx512dq,no-evex512") +#define __DISABLE_AVX512VLDQ__ +#endif /* __AVX512VLDQ__ */ + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttpd_epi64 (__m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttpd_epi64 (__mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttpd_epi64 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttpd_epi64 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttpd_epu64 (__m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttpd_epu64 (__mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttpd_epu64 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttpd_epu64 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_epi64 (__m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_epi64 (__mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_epi64 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_epi64 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_epu64 (__m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_epu64 (__mmask8 __U, __m256d __A) +{ + return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_epu64 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_epu64 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttps_epi64 (__m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttps_epi64 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttps_epu64 (__m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttps_epu64 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_f64x2 (__m128d __A) +{ + return (__m256d) __builtin_ia32_broadcastf64x2_256_mask ((__v2df) + __A, + (__v4df)_mm256_avx512_undefined_pd(), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_f64x2 (__m256d __O, __mmask8 __M, __m128d __A) +{ + return (__m256d) __builtin_ia32_broadcastf64x2_256_mask ((__v2df) + __A, + (__v4df) + __O, __M); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A) +{ + return (__m256d) __builtin_ia32_broadcastf64x2_256_mask ((__v2df) + __A, + (__v4df) + _mm256_avx512_setzero_ps (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_i64x2 (__m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti64x2_256_mask ((__v2di) + __A, + (__v4di)_mm256_avx512_undefined_si256(), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_i64x2 (__m256i __O, __mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti64x2_256_mask ((__v2di) + __A, + (__v4di) + __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti64x2_256_mask ((__v2di) + __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_f32x2 (__m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A, + (__v8sf)_mm256_avx512_undefined_ps(), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A, + (__v8sf) __O, + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_i32x2 (__m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) + __A, + (__v8si)_mm256_avx512_undefined_si256(), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) + __A, + (__v8si) + __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) + __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcast_i32x2 (__m128i __A) +{ + return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) + __A, + (__v4si)_mm_avx512_undefined_si128(), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) + __A, + (__v4si) + __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) + __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mullo_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du) __A * (__v4du) __B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mullo_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mullo_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mullo_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du) __A * (__v2du) __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mullo_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mullo_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_andnot_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_andnot_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_andnot_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_andnot_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_andnot_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B) +{ + return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_andnot_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_andnot_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_andnot_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_epi64 (__m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_epi64 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_epu64 (__m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) +{ + return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_epu64 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_ps (__m256i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m256i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_ps (__mmask8 __U, __m256i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_ps (__m128i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_ps (__mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu64_ps (__m256i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m256i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu64_ps (__mmask8 __U, __m256i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu64_ps (__m128i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu64_ps (__mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_pd (__m256i __A) +{ + return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_pd (__m256d __W, __mmask8 __U, __m256i __A) +{ + return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_pd (__mmask8 __U, __m256i __A) +{ + return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_pd (__m128i __A) +{ + return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_pd (__m128d __W, __mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_pd (__mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu64_pd (__m256i __A) +{ + return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu64_pd (__m256d __W, __mmask8 __U, __m256i __A) +{ + return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu64_pd (__mmask8 __U, __m256i __A) +{ + return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_and_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_and_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_and_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_and_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_and_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_and_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_and_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_and_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu64_pd (__m128i __A) +{ + return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu64_pd (__m128d __W, __mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu64_pd (__mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_xor_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_xor_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_xor_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_xor_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_xor_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_xor_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_xor_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_or_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_or_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_or_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_or_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_or_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_or_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_or_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_or_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movm_epi32 (__mmask8 __A) +{ + return (__m128i) __builtin_ia32_cvtmask2d128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movm_epi32 (__mmask8 __A) +{ + return (__m256i) __builtin_ia32_cvtmask2d256 (__A); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movm_epi64 (__mmask8 __A) +{ + return (__m128i) __builtin_ia32_cvtmask2q128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movm_epi64 (__mmask8 __A) +{ + return (__m256i) __builtin_ia32_cvtmask2q256 (__A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movepi32_mask (__m128i __A) +{ + return (__mmask8) __builtin_ia32_cvtd2mask128 ((__v4si) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movepi32_mask (__m256i __A) +{ + return (__mmask8) __builtin_ia32_cvtd2mask256 ((__v8si) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movepi64_mask (__m128i __A) +{ + return (__mmask8) __builtin_ia32_cvtq2mask128 ((__v2di) __A); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movepi64_mask (__m256i __A) +{ + return (__mmask8) __builtin_ia32_cvtq2mask256 ((__v4di) __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extractf64x2_pd (__m256d __A, const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df) __A, + __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_extractf64x2_pd (__m128d __W, __mmask8 __U, __m256d __A, + const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df) __A, + __imm, + (__v2df) __W, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_extractf64x2_pd (__mmask8 __U, __m256d __A, + const int __imm) +{ + return (__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df) __A, + __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extracti64x2_epi64 (__m256i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di) __A, + __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_extracti64x2_epi64 (__m128i __W, __mmask8 __U, __m256i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di) __A, + __imm, + (__v2di) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_extracti64x2_epi64 (__mmask8 __U, __m256i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di) __A, + __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_pd (__m256d __A, int __B) +{ + return (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_pd (__m256d __W, __mmask8 __U, __m256d __A, int __B) +{ + return (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_reduce_pd (__mmask8 __U, __m256d __A, int __B) +{ + return (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_pd (__m128d __A, int __B) +{ + return (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_pd (__m128d __W, __mmask8 __U, __m128d __A, int __B) +{ + return (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_pd (__mmask8 __U, __m128d __A, int __B) +{ + return (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_reduce_ps (__m256 __A, int __B) +{ + return (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_reduce_ps (__m256 __W, __mmask8 __U, __m256 __A, int __B) +{ + return (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_reduce_ps (__mmask8 __U, __m256 __A, int __B) +{ + return (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_reduce_ps (__m128 __A, int __B) +{ + return (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_reduce_ps (__m128 __W, __mmask8 __U, __m128 __A, int __B) +{ + return (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_reduce_ps (__mmask8 __U, __m128 __A, int __B) +{ + return (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_range_pd (__m256d __A, __m256d __B, int __C) +{ + return (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, + (__v4df) __B, __C, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_range_pd (__m256d __W, __mmask8 __U, + __m256d __A, __m256d __B, int __C) +{ + return (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, + (__v4df) __B, __C, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_range_pd (__mmask8 __U, __m256d __A, __m256d __B, int __C) +{ + return (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, + (__v4df) __B, __C, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_pd (__m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_pd (__m128d __W, __mmask8 __U, + __m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_pd (__mmask8 __U, __m128d __A, __m128d __B, int __C) +{ + return (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, + (__v2df) __B, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_range_ps (__m256 __A, __m256 __B, int __C) +{ + return (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, + (__v8sf) __B, __C, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_range_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B, + int __C) +{ + return (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, + (__v8sf) __B, __C, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_range_ps (__mmask8 __U, __m256 __A, __m256 __B, int __C) +{ + return (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, + (__v8sf) __B, __C, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_range_ps (__m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_range_ps (__m128 __W, __mmask8 __U, + __m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_range_ps (__mmask8 __U, __m128 __A, __m128 __B, int __C) +{ + return (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, + (__v4sf) __B, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fpclass_pd_mask (__mmask8 __U, __m256d __A, + const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd256_mask ((__v4df) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fpclass_pd_mask (__m256d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd256_mask ((__v4df) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fpclass_ps_mask (__mmask8 __U, __m256 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassps256_mask ((__v8sf) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fpclass_ps_mask (__m256 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassps256_mask ((__v8sf) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fpclass_pd_mask (__mmask8 __U, __m128d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd128_mask ((__v2df) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_pd_mask (__m128d __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclasspd128_mask ((__v2df) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fpclass_ps_mask (__mmask8 __U, __m128 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassps128_mask ((__v4sf) __A, + __imm, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fpclass_ps_mask (__m128 __A, const int __imm) +{ + return (__mmask8) __builtin_ia32_fpclassps128_mask ((__v4sf) __A, + __imm, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_inserti64x2 (__m256i __A, __m128i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di) __A, + (__v2di) __B, + __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_inserti64x2 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di) __A, + (__v2di) __B, + __imm, + (__v4di) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_inserti64x2 (__mmask8 __U, __m256i __A, __m128i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di) __A, + (__v2di) __B, + __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insertf64x2 (__m256d __A, __m128d __B, const int __imm) +{ + return (__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df) __A, + (__v2df) __B, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_insertf64x2 (__m256d __W, __mmask8 __U, __m256d __A, + __m128d __B, const int __imm) +{ + return (__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df) __A, + (__v2df) __B, + __imm, + (__v4df) __W, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_insertf64x2 (__mmask8 __U, __m256d __A, __m128d __B, + const int __imm) +{ + return (__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df) __A, + (__v2df) __B, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) + __U); +} + +#else +#define _mm256_insertf64x2(X, Y, C) \ + ((__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df)(__m256d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd(), \ + (__mmask8)-1)) + +#define _mm256_mask_insertf64x2(W, U, X, Y, C) \ + ((__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df)(__m256d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_insertf64x2(U, X, Y, C) \ + ((__m256d) __builtin_ia32_insertf64x2_256_mask ((__v4df)(__m256d) (X),\ + (__v2df)(__m128d) (Y), (int) (C), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd(), \ + (__mmask8)(U))) + +#define _mm256_inserti64x2(X, Y, C) \ + ((__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di)(__m256i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)-1)) + +#define _mm256_mask_inserti64x2(W, U, X, Y, C) \ + ((__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di)(__m256i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_inserti64x2(U, X, Y, C) \ + ((__m256i) __builtin_ia32_inserti64x2_256_mask ((__v4di)(__m256i) (X),\ + (__v2di)(__m128i) (Y), (int) (C), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm256_extractf64x2_pd(X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df)(__m256d) (X),\ + (int) (C), (__v2df)(__m128d) _mm_avx512_setzero_pd(), (__mmask8)-1)) + +#define _mm256_mask_extractf64x2_pd(W, U, X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df)(__m256d) (X),\ + (int) (C), (__v2df)(__m128d) (W), (__mmask8) (U))) + +#define _mm256_maskz_extractf64x2_pd(U, X, C) \ + ((__m128d) __builtin_ia32_extractf64x2_256_mask ((__v4df)(__m256d) (X),\ + (int) (C), (__v2df)(__m128d) _mm_avx512_setzero_pd(), (__mmask8) (U))) + +#define _mm256_extracti64x2_epi64(X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di)(__m256i) (X),\ + (int) (C), (__v2di)(__m128i) _mm_avx512_setzero_si128 (), (__mmask8)-1)) + +#define _mm256_mask_extracti64x2_epi64(W, U, X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di)(__m256i) (X),\ + (int) (C), (__v2di)(__m128i) (W), (__mmask8) (U))) + +#define _mm256_maskz_extracti64x2_epi64(U, X, C) \ + ((__m128i) __builtin_ia32_extracti64x2_256_mask ((__v4di)(__m256i) (X),\ + (int) (C), (__v2di)(__m128i) _mm_avx512_setzero_si128 (), (__mmask8) (U))) + +#define _mm256_reduce_pd(A, B) \ + ((__m256d) __builtin_ia32_reducepd256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)_mm256_avx512_setzero_pd(), (__mmask8)-1)) + +#define _mm256_mask_reduce_pd(W, U, A, B) \ + ((__m256d) __builtin_ia32_reducepd256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)(W), (__mmask8)(U))) + +#define _mm256_maskz_reduce_pd(U, A, B) \ + ((__m256d) __builtin_ia32_reducepd256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)_mm256_avx512_setzero_pd(), (__mmask8)(U))) + +#define _mm_reduce_pd(A, B) \ + ((__m128d) __builtin_ia32_reducepd128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)_mm_avx512_setzero_pd(), (__mmask8)-1)) + +#define _mm_mask_reduce_pd(W, U, A, B) \ + ((__m128d) __builtin_ia32_reducepd128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)(__m128d)(W), (__mmask8)(U))) + +#define _mm_maskz_reduce_pd(U, A, B) \ + ((__m128d) __builtin_ia32_reducepd128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)_mm_avx512_setzero_pd(), (__mmask8)(U))) + +#define _mm256_reduce_ps(A, B) \ + ((__m256) __builtin_ia32_reduceps256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)_mm256_avx512_setzero_ps(), (__mmask8)-1)) + +#define _mm256_mask_reduce_ps(W, U, A, B) \ + ((__m256) __builtin_ia32_reduceps256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)(__m256)(W), (__mmask8)(U))) + +#define _mm256_maskz_reduce_ps(U, A, B) \ + ((__m256) __builtin_ia32_reduceps256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)_mm256_avx512_setzero_ps(), (__mmask8)(U))) + +#define _mm_reduce_ps(A, B) \ + ((__m128) __builtin_ia32_reduceps128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)_mm_avx512_setzero_ps(), (__mmask8)-1)) + +#define _mm_mask_reduce_ps(W, U, A, B) \ + ((__m128) __builtin_ia32_reduceps128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)(__m128)(W), (__mmask8)(U))) + +#define _mm_maskz_reduce_ps(U, A, B) \ + ((__m128) __builtin_ia32_reduceps128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)_mm_avx512_setzero_ps(), (__mmask8)(U))) + +#define _mm256_range_pd(A, B, C) \ + ((__m256d) __builtin_ia32_rangepd256_mask ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(C), \ + (__v4df)_mm256_avx512_setzero_pd(), (__mmask8)-1)) + +#define _mm256_maskz_range_pd(U, A, B, C) \ + ((__m256d) __builtin_ia32_rangepd256_mask ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(C), \ + (__v4df)_mm256_avx512_setzero_pd(), (__mmask8)(U))) + +#define _mm_range_pd(A, B, C) \ + ((__m128d) __builtin_ia32_rangepd128_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), \ + (__v2df)_mm_avx512_setzero_pd(), (__mmask8)-1)) + +#define _mm256_range_ps(A, B, C) \ + ((__m256) __builtin_ia32_rangeps256_mask ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(C), \ + (__v8sf)_mm256_avx512_setzero_ps(), (__mmask8)-1)) + +#define _mm256_mask_range_ps(W, U, A, B, C) \ + ((__m256) __builtin_ia32_rangeps256_mask ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(C), \ + (__v8sf)(__m256)(W), (__mmask8)(U))) + +#define _mm256_maskz_range_ps(U, A, B, C) \ + ((__m256) __builtin_ia32_rangeps256_mask ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(C), \ + (__v8sf)_mm256_avx512_setzero_ps(), (__mmask8)(U))) + +#define _mm_range_ps(A, B, C) \ + ((__m128) __builtin_ia32_rangeps128_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), \ + (__v4sf)_mm_avx512_setzero_ps(), (__mmask8)-1)) + +#define _mm_mask_range_ps(W, U, A, B, C) \ + ((__m128) __builtin_ia32_rangeps128_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), \ + (__v4sf)(__m128)(W), (__mmask8)(U))) + +#define _mm_maskz_range_ps(U, A, B, C) \ + ((__m128) __builtin_ia32_rangeps128_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), \ + (__v4sf)_mm_avx512_setzero_ps(), (__mmask8)(U))) + +#define _mm256_mask_range_pd(W, U, A, B, C) \ + ((__m256d) __builtin_ia32_rangepd256_mask ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(C), \ + (__v4df)(__m256d)(W), (__mmask8)(U))) + +#define _mm_mask_range_pd(W, U, A, B, C) \ + ((__m128d) __builtin_ia32_rangepd128_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), \ + (__v2df)(__m128d)(W), (__mmask8)(U))) + +#define _mm_maskz_range_pd(U, A, B, C) \ + ((__m128d) __builtin_ia32_rangepd128_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), \ + (__v2df)_mm_avx512_setzero_pd(), (__mmask8)(U))) + +#define _mm256_mask_fpclass_pd_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd256_mask ((__v4df) (__m256d) (X), \ + (int) (C),(__mmask8)(u))) + +#define _mm256_mask_fpclass_ps_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclassps256_mask ((__v8sf) (__m256) (X), \ + (int) (C),(__mmask8)(u))) + +#define _mm_mask_fpclass_pd_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd128_mask ((__v2df) (__m128d) (X), \ + (int) (C),(__mmask8)(u))) + +#define _mm_mask_fpclass_ps_mask(u, X, C) \ + ((__mmask8) __builtin_ia32_fpclassps128_mask ((__v4sf) (__m128) (X), \ + (int) (C),(__mmask8)(u))) + +#define _mm256_fpclass_pd_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd256_mask ((__v4df) (__m256d) (X), \ + (int) (C),(__mmask8)-1)) + +#define _mm256_fpclass_ps_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclassps256_mask ((__v8sf) (__m256) (X), \ + (int) (C),(__mmask8)-1)) + +#define _mm_fpclass_pd_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclasspd128_mask ((__v2df) (__m128d) (X), \ + (int) (C),(__mmask8)-1)) + +#define _mm_fpclass_ps_mask(X, C) \ + ((__mmask8) __builtin_ia32_fpclassps128_mask ((__v4sf) (__m128) (X), \ + (int) (C),(__mmask8)-1)) + +#endif + +#ifdef __DISABLE_AVX512VLDQ__ +#undef __DISABLE_AVX512VLDQ__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VLDQ__ */ + +#endif /* _AVX512VLDQINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vlintrin.h b/template/sysroot/include/avx512vlintrin.h new file mode 100644 index 0000000..ca3b578 --- /dev/null +++ b/template/sysroot/include/avx512vlintrin.h @@ -0,0 +1,13929 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VLINTRIN_H_INCLUDED +#define _AVX512VLINTRIN_H_INCLUDED + +#if !defined (__AVX512VL__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vl,no-evex512") +#define __DISABLE_AVX512VL__ +#endif /* __AVX512VL__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef unsigned int __mmask32; +typedef int __v4si_u __attribute__ ((__vector_size__ (16), \ + __may_alias__, __aligned__ (1))); +typedef int __v8si_u __attribute__ ((__vector_size__ (32), \ + __may_alias__, __aligned__ (1))); +typedef long long __v2di_u __attribute__ ((__vector_size__ (16), \ + __may_alias__, __aligned__ (1))); +typedef long long __v4di_u __attribute__ ((__vector_size__ (32), \ + __may_alias__, __aligned__ (1))); + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_undefined_si128 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128i __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_undefined_ps (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256 __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_undefined_pd (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256d __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_undefined_si256 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256i __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avx512_setzero_si128 (void) +{ + return __extension__ (__m128i)(__v4si){ 0, 0, 0, 0 }; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_setzero_ps (void) +{ + return __extension__ (__m256){ 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_setzero_pd (void) +{ + return __extension__ (__m256d){ 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_avx512_setzero_si256 (void) +{ + return __extension__ (__m256i)(__v4di){ 0, 0, 0, 0 }; +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_movapd256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_movapd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_movapd128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_movapd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_load_pd (__m256d __W, __mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_load_pd (__mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_pd (__m128d __W, __mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_pd (__mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_store_pd (void *__P, __mmask8 __U, __m256d __A) +{ + __builtin_ia32_storeapd256_mask ((__v4df *) __P, + (__v4df) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_pd (void *__P, __mmask8 __U, __m128d __A) +{ + __builtin_ia32_storeapd128_mask ((__v2df *) __P, + (__v2df) __A, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movaps256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movaps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movaps128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movaps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_load_ps (__m256 __W, __mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_load_ps (__mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_ps (__m128 __W, __mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_ps (__mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A) +{ + __builtin_ia32_storeaps256_mask ((__v8sf *) __P, + (__v8sf) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_ps (void *__P, __mmask8 __U, __m128 __A) +{ + __builtin_ia32_storeaps128_mask ((__v4sf *) __P, + (__v4sf) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdqa64_256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdqa64_256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdqa64_128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdqa64_128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_epi64 (void const *__P) +{ + return (__m256i) (*(__v4di *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P, + (__v4di) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_load_epi64 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_epi64 (void const *__P) +{ + return (__m128i) (*(__v2di *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P, + (__v2di) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_epi64 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_movdqa64store256_mask ((__v4di *) __P, + (__v4di) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_movdqa64store128_mask ((__v2di *) __P, + (__v2di) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mov_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdqa32_256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_movdqa32_256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mov_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdqa32_128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mov_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_movdqa32_128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_epi32 (void const *__P) +{ + return (__m256i) (*(__v8si *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P, + (__v8si) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_load_epi32 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_epi32 (void const *__P) +{ + return (__m128i) (*(__v4si *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P, + (__v4si) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_load_epi32 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_epi32 (void *__P, __m256i __A) +{ + *(__v8si *) __P = (__v8si) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_movdqa32store256_mask ((__v8si *) __P, + (__v8si) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_epi32 (void *__P, __m128i __A) +{ + *(__v4si *) __P = (__v4si) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_movdqa32store128_mask ((__v4si *) __P, + (__v4si) __A, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_subpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_subpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_subpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_subpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_epi64 (void *__P, __m256i __A) +{ + *(__m256i *) __P = __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_epi64 (void *__P, __m128i __A) +{ + *(__m128i *) __P = __A; +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_loadupd256_mask ((const double *) __P, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_pd (__mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_loadupd256_mask ((const double *) __P, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_pd (__m128d __W, __mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_loadupd128_mask ((const double *) __P, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_pd (__mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_loadupd128_mask ((const double *) __P, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_pd (void *__P, __mmask8 __U, __m256d __A) +{ + __builtin_ia32_storeupd256_mask ((double *) __P, + (__v4df) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_pd (void *__P, __mmask8 __U, __m128d __A) +{ + __builtin_ia32_storeupd128_mask ((double *) __P, + (__v2df) __A, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_ps (__m256 __W, __mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_loadups256_mask ((const float *) __P, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_ps (__mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_loadups256_mask ((const float *) __P, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_ps (__m128 __W, __mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_loadups128_mask ((const float *) __P, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_ps (__mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_loadups128_mask ((const float *) __P, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_ps (void *__P, __mmask8 __U, __m256 __A) +{ + __builtin_ia32_storeups256_mask ((float *) __P, + (__v8sf) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_ps (void *__P, __mmask8 __U, __m128 __A) +{ + __builtin_ia32_storeups128_mask ((float *) __P, + (__v4sf) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_epi64 (void const *__P) +{ + return (__m256i) (*(__v4di_u *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddqudi256_mask ((const long long *) __P, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddqudi256_mask ((const long long *) __P, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_epi64 (void const *__P) +{ + return (__m128i) (*(__v2di_u *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddqudi128_mask ((const long long *) __P, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddqudi128_mask ((const long long *) __P, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi64 (void *__P, __m256i __A) +{ + *(__m256i_u *) __P = (__m256i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_storedqudi256_mask ((long long *) __P, + (__v4di) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi64 (void *__P, __m128i __A) +{ + *(__m128i_u *) __P = (__m128i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_storedqudi128_mask ((long long *) __P, + (__v2di) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_epi32 (void const *__P) +{ + return (__m256i) (*(__v8si_u *) __P); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddqusi256_mask ((const int *) __P, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_loadu_epi32 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_loaddqusi256_mask ((const int *) __P, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_epi32 (void const *__P) +{ + return (__m128i) (*(__v4si_u *) __P); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddqusi128_mask ((const int *) __P, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_loaddqusi128_mask ((const int *) __P, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi32 (void *__P, __m256i __A) +{ + *(__m256i_u *) __P = (__m256i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_storedqusi256_mask ((int *) __P, + (__v8si) __A, + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi32 (void *__P, __m128i __A) +{ + *(__m128i_u *) __P = (__m128i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_storedqusi128_mask ((int *) __P, + (__v4si) __A, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_pd (__mmask8 __U, __m256d __A, __m256d __W) +{ + return (__m256d) __builtin_ia32_blendmpd_256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_ps (__mmask8 __U, __m256 __A, __m256 __W) +{ + return (__m256) __builtin_ia32_blendmps_256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_epi64 (__mmask8 __U, __m256i __A, __m256i __W) +{ + return (__m256i) __builtin_ia32_blendmq_256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_blend_epi32 (__mmask8 __U, __m256i __A, __m256i __W) +{ + return (__m256i) __builtin_ia32_blendmd_256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_pd (__mmask8 __U, __m128d __A, __m128d __W) +{ + return (__m128d) __builtin_ia32_blendmpd_128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_ps (__mmask8 __U, __m128 __A, __m128 __W) +{ + return (__m128) __builtin_ia32_blendmps_128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_epi64 (__mmask8 __U, __m128i __A, __m128i __W) +{ + return (__m128i) __builtin_ia32_blendmq_128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_blend_epi32 (__mmask8 __U, __m128i __A, __m128i __W) +{ + return (__m128i) __builtin_ia32_blendmd_128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_abs_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_abs_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_abs_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_abs_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_abs_epi64 (__m256i __A) +{ + return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_abs_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_abs_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_epi64 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_abs_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_abs_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_epu32 (__m256d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_epu32 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttps_epi32 (__mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttps_epi32 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttps_epu32 (__m256 __A) +{ + return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttps_epu32 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttpd_epi32 (__mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttpd_epu32 (__m256d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttpd_epu32 (__m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_epi32 (__mmask8 __U, __m256d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) +{ + return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_pd (__m256d __W, __mmask8 __U, __m128i __A) +{ + return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) +{ + return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_pd (__m128d __W, __mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu32_pd (__m128i __A) +{ + return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu32_pd (__m256d __W, __mmask8 __U, __m128i __A) +{ + return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) +{ + return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu32_pd (__m128i __A) +{ + return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu32_pd (__m128d __W, __mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) +{ + return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_ps (__m256 __W, __mmask8 __U, __m256i __A) +{ + return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_ps (__mmask8 __U, __m256i __A) +{ + return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_ps (__m128 __W, __mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_ps (__mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepu32_ps (__m256i __A) +{ + return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu32_ps (__m256 __W, __mmask8 __U, __m256i __A) +{ + return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu32_ps (__mmask8 __U, __m256i __A) +{ + return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu32_ps (__m128i __A) +{ + return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu32_ps (__m128 __W, __mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu32_ps (__mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_pd (__m256d __W, __mmask8 __U, __m128 __A) +{ + return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_pd (__mmask8 __U, __m128 __A) +{ + return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_pd (__m128d __W, __mmask8 __U, __m128 __A) +{ + return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_pd (__mmask8 __U, __m128 __A) +{ + return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovdb128mem_mask ((unsigned int *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, + (__v16qi) __O, __M); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovdb256mem_mask ((unsigned long long *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi32_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovsdb128mem_mask ((unsigned int *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi32_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi32_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovsdb256mem_mask ((unsigned long long *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi32_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi32_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovusdb128mem_mask ((unsigned int *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi32_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi32_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovusdb256mem_mask ((unsigned long long *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi32_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovdw128mem_mask ((unsigned long long *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi32_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovsdw128mem_mask ((unsigned long long *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, + (__v8hi)__O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi32_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi32_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovsdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi32_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi32_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovusdw128mem_mask ((unsigned long long *) __P, (__v4si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi32_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi32_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovusdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi32_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovqb128mem_mask ((unsigned short *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovqb256mem_mask ((unsigned int *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi64_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovsqb128mem_mask ((unsigned short *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi64_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi64_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovsqb256mem_mask ((unsigned int *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, + (__v16qi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi64_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi64_epi8 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovusqb128mem_mask ((unsigned short *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi64_epi8 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi64_epi8 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovusqb256mem_mask ((unsigned int *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, + (__v16qi) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi64_epi8 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, + (__v16qi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovqw128mem_mask ((unsigned int *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, + (__v8hi)__O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovqw256mem_mask ((unsigned long long *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi64_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovsqw128mem_mask ((unsigned int *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi64_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi64_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovsqw256mem_mask ((unsigned long long *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi64_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi64_epi16 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovusqw128mem_mask ((unsigned int *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi64_epi16 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi64_epi16 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovusqw256mem_mask ((unsigned long long *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, + (__v8hi) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi64_epi16 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, + (__v8hi) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi64_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovqd128mem_mask ((unsigned long long *) __P, + (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, + (__v4si) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi64_epi32 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi64_epi32 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A, + (__v4si) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi64_epi32 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsepi64_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovsqd128mem_mask ((unsigned long long *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, + (__v4si) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtsepi64_epi32 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsepi64_epi32 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovsqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, + (__v4si)__O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtsepi64_epi32 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtusepi64_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) +{ + __builtin_ia32_pmovusqd128mem_mask ((unsigned long long *) __P, (__v2di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, + (__v4si) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtusepi64_epi32 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtusepi64_epi32 (__m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_undefined_si128 (), + (__mmask8) -1); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) +{ + __builtin_ia32_pmovusqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, + (__v4si) __O, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtusepi64_epi32 (__mmask8 __M, __m256i __A) +{ + return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastss_ps (__m256 __O, __mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastss256_mask ((__v4sf) __A, + (__v8sf) __O, + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastss256_mask ((__v4sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + __M); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcastss_ps (__m128 __O, __mmask8 __M, __m128 __A) +{ + return (__m128) __builtin_ia32_broadcastss128_mask ((__v4sf) __A, + (__v4sf) __O, + __M); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) +{ + return (__m128) __builtin_ia32_broadcastss128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + __M); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastsd_pd (__m256d __O, __mmask8 __M, __m128d __A) +{ + return (__m256d) __builtin_ia32_broadcastsd256_mask ((__v2df) __A, + (__v4df) __O, + __M); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) +{ + return (__m256d) __builtin_ia32_broadcastsd256_mask ((__v2df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastd_epi32 (__m256i __O, __mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastd256_mask ((__v4si) __A, + (__v8si) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastd256_mask ((__v4si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_set1_epi32 (__m256i __O, __mmask8 __M, int __A) +{ + return (__m256i) __builtin_ia32_pbroadcastd256_gpr_mask (__A, (__v8si) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_set1_epi32 (__mmask8 __M, int __A) +{ + return (__m256i) __builtin_ia32_pbroadcastd256_gpr_mask (__A, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcastd_epi32 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastd128_mask ((__v4si) __A, + (__v4si) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastd128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_set1_epi32 (__m128i __O, __mmask8 __M, int __A) +{ + return (__m128i) __builtin_ia32_pbroadcastd128_gpr_mask (__A, (__v4si) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_set1_epi32 (__mmask8 __M, int __A) +{ + return (__m128i) + __builtin_ia32_pbroadcastd128_gpr_mask (__A, + (__v4si) _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcastq_epi64 (__m256i __O, __mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastq256_mask ((__v2di) __A, + (__v4di) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_pbroadcastq256_mask ((__v2di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A) +{ + return (__m256i) __builtin_ia32_pbroadcastq256_gpr_mask (__A, (__v4di) __O, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_set1_epi64 (__mmask8 __M, long long __A) +{ + return (__m256i) __builtin_ia32_pbroadcastq256_gpr_mask (__A, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_broadcastq_epi64 (__m128i __O, __mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastq128_mask ((__v2di) __A, + (__v2di) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) +{ + return (__m128i) __builtin_ia32_pbroadcastq128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A) +{ + return (__m128i) __builtin_ia32_pbroadcastq128_gpr_mask (__A, (__v2di) __O, + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_set1_epi64 (__mmask8 __M, long long __A) +{ + return (__m128i) + __builtin_ia32_pbroadcastq128_gpr_mask (__A, + (__v2di) _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_f32x4 (__m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x4_256_mask ((__v4sf) __A, + (__v8sf)_mm256_avx512_undefined_pd (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_f32x4 (__m256 __O, __mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x4_256_mask ((__v4sf) __A, + (__v8sf) __O, + __M); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_f32x4 (__mmask8 __M, __m128 __A) +{ + return (__m256) __builtin_ia32_broadcastf32x4_256_mask ((__v4sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_i32x4 (__m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x4_256_mask ((__v4si) + __A, + (__v8si)_mm256_avx512_undefined_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_broadcast_i32x4 (__m256i __O, __mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x4_256_mask ((__v4si) + __A, + (__v8si) + __O, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_broadcast_i32x4 (__mmask8 __M, __m128i __A) +{ + return (__m256i) __builtin_ia32_broadcasti32x4_256_mask ((__v4si) + __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi8_epi32 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbd256_mask ((__v16qi) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi8_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbd256_mask ((__v16qi) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi8_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbd128_mask ((__v16qi) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi8_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbd128_mask ((__v16qi) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi8_epi64 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbq256_mask ((__v16qi) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxbq256_mask ((__v16qi) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi8_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbq128_mask ((__v16qi) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxbq128_mask ((__v16qi) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi16_epi32 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxwd256_mask ((__v8hi) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi16_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxwd256_mask ((__v8hi) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi16_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxwd128_mask ((__v8hi) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi16_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxwd128_mask ((__v8hi) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi16_epi64 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxwq256_mask ((__v8hi) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovsxwq256_mask ((__v8hi) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi16_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxwq128_mask ((__v8hi) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovsxwq128_mask ((__v8hi) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepi32_epi64 (__m256i __W, __mmask8 __U, __m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxdq256_mask ((__v4si) __X, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepi32_epi64 (__mmask8 __U, __m128i __X) +{ + return (__m256i) __builtin_ia32_pmovsxdq256_mask ((__v4si) __X, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepi32_epi64 (__m128i __W, __mmask8 __U, __m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxdq128_mask ((__v4si) __X, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepi32_epi64 (__mmask8 __U, __m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxdq128_mask ((__v4si) __X, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu8_epi32 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbd256_mask ((__v16qi) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu8_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbd256_mask ((__v16qi) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu8_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbd128_mask ((__v16qi) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu8_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbd128_mask ((__v16qi) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu8_epi64 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbq256_mask ((__v16qi) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxbq256_mask ((__v16qi) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu8_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbq128_mask ((__v16qi) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxbq128_mask ((__v16qi) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu16_epi32 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxwd256_mask ((__v8hi) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu16_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxwd256_mask ((__v8hi) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu16_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxwd128_mask ((__v8hi) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu16_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxwd128_mask ((__v8hi) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu16_epi64 (__m256i __W, __mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxwq256_mask ((__v8hi) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m256i) __builtin_ia32_pmovzxwq256_mask ((__v8hi) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu16_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxwq128_mask ((__v8hi) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu16_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_pmovzxwq128_mask ((__v8hi) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtepu32_epi64 (__m256i __W, __mmask8 __U, __m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxdq256_mask ((__v4si) __X, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtepu32_epi64 (__mmask8 __U, __m128i __X) +{ + return (__m256i) __builtin_ia32_pmovzxdq256_mask ((__v4si) __X, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtepu32_epi64 (__m128i __W, __mmask8 __U, __m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxdq128_mask ((__v4si) __X, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtepu32_epi64 (__mmask8 __U, __m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxdq128_mask ((__v4si) __X, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rcp14_pd (__m256d __A) +{ + return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rcp14_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rcp14_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp14_pd (__m128d __A) +{ + return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp14_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp14_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rcp14_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rcp14_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp14_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rcp14_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rcp14_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rsqrt14_pd (__m256d __A) +{ + return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rsqrt14_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rsqrt14_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt14_pd (__m128d __A) +{ + return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt14_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt14_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rsqrt14_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rsqrt14_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rsqrt14_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt14_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rsqrt14_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rsqrt14_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sqrt_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_sqrtpd256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sqrt_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_sqrtpd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_sqrtpd128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_sqrtpd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sqrt_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_sqrtps256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sqrt_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_sqrtps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sqrt_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_sqrtps128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sqrt_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_sqrtps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_add_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_add_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sub_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sub_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_add_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_add_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sub_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sub_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getexp_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getexp_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getexp_pd (__m256d __A) +{ + return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getexp_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getexp_pd (__m128d __A) +{ + return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getexp_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srl_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psrld256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srl_epi32 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psrld256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srl_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srl_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srl_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psrlq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srl_epi64 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psrlq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srl_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srl_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrlq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_and_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pandd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_and_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pandd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_scalef_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_scalef_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B) +{ + return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_pd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_scalef_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmadd_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmadd_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfmaddpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmadd_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_pd (__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmaddpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmadd_ps (__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmadd_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfmaddps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmadd_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmadd_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmadd_ps (__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmaddps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmadd_ps (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsub_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmsubpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsub_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfmsubpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsub_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmsubpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_pd (__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmsubpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmsubpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmsubpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsub_ps (__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmsubps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsub_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfmsubps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsub_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmsubps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsub_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmsubps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsub_ps (__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmsubps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsub_ps (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmsubps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmaddsub_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmaddsub_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmaddsub_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmaddsub_pd (__m128d __A, __mmask8 __U, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmaddsub_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmaddsub_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmaddsub_ps (__m256 __A, __mmask8 __U, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmaddsub_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfmaddsubps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmaddsub_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmaddsub_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmaddsub_ps (__m128 __A, __m128 __B, __m128 __C, + __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmaddsubps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmaddsub_ps (__mmask8 __U, __m128 __A, __m128 __B, + __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsubadd_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A, + (__v4df) __B, + -(__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsubadd_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfmsubaddpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsubadd_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A, + (__v4df) __B, + -(__v4df) __C, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsubadd_pd (__m128d __A, __mmask8 __U, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A, + (__v2df) __B, + -(__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsubadd_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfmsubaddpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsubadd_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A, + (__v2df) __B, + -(__v2df) __C, + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fmsubadd_ps (__m256 __A, __mmask8 __U, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A, + (__v8sf) __B, + -(__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fmsubadd_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfmsubaddps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fmsubadd_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A, + (__v8sf) __B, + -(__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fmsubadd_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A, + (__v4sf) __B, + -(__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fmsubadd_ps (__m128 __A, __m128 __B, __m128 __C, + __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfmsubaddps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fmsubadd_ps (__mmask8 __U, __m128 __A, __m128 __B, + __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A, + (__v4sf) __B, + -(__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmadd_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfnmaddpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmadd_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfnmaddpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmadd_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfnmaddpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_pd (__m128d __A, __mmask8 __U, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfnmaddpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfnmaddpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfnmaddpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmadd_ps (__m256 __A, __mmask8 __U, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfnmaddps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmadd_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfnmaddps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmadd_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfnmaddps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmadd_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfnmaddps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmadd_ps (__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfnmaddps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmadd_ps (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfnmaddps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmsub_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfnmsubpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmsub_pd (__m256d __A, __m256d __B, __m256d __C, + __mmask8 __U) +{ + return (__m256d) __builtin_ia32_vfnmsubpd256_mask3 ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmsub_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256d __C) +{ + return (__m256d) __builtin_ia32_vfnmsubpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_pd (__m128d __A, __mmask8 __U, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfnmsubpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_pd (__m128d __A, __m128d __B, __m128d __C, + __mmask8 __U) +{ + return (__m128d) __builtin_ia32_vfnmsubpd128_mask3 ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128d __C) +{ + return (__m128d) __builtin_ia32_vfnmsubpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2df) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fnmsub_ps (__m256 __A, __mmask8 __U, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfnmsubps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask3_fnmsub_ps (__m256 __A, __m256 __B, __m256 __C, + __mmask8 __U) +{ + return (__m256) __builtin_ia32_vfnmsubps256_mask3 ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fnmsub_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256 __C) +{ + return (__m256) __builtin_ia32_vfnmsubps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fnmsub_ps (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfnmsubps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask3_fnmsub_ps (__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) +{ + return (__m128) __builtin_ia32_vfnmsubps128_mask3 ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fnmsub_ps (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfnmsubps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __C, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_and_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pandd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_and_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pandd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_andnot_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pandnd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_andnot_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pandnd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_andnot_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pandnd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pandnd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pord256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_or_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pord256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_or_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8su)__A | (__v8su)__B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_or_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pord128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_or_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pord128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4su)__A | (__v4su)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_xor_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pxord256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_xor_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pxord256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_xor_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v8su)__A ^ (__v8su)__B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_xor_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pxord128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_xor_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pxord128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4su)__A ^ (__v4su)__B); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m128d __A) +{ + return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) +{ + return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m256d __A) +{ + return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtpd_ps (__mmask8 __U, __m256d __A) +{ + return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_epi32 (__mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_epi32 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_epu32 (__m256 __A) +{ + return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) +{ + return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_epu32 (__m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) +{ + return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_movedup_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_movddup256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_movddup256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_movedup_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_movddup128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_movedup_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_movddup128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_movehdup_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movshdup256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_movehdup_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movshdup256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movshdup128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_movehdup_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movshdup128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_moveldup_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movsldup256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_movsldup256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_moveldup_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movsldup128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_moveldup_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_movsldup128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhdq128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhdq128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhdq256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhdq256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhqdq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckhqdq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhqdq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckhqdq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckldq128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpckldq128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckldq256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpckldq256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklqdq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_punpcklqdq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklqdq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_punpcklqdq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epu32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __A, + (__v4si) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqd128_mask ((__v4si) __A, + (__v4si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epu32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __A, + (__v4si) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqd128_mask ((__v4si) __A, + (__v4si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epu32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __A, + (__v8si) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqd256_mask ((__v8si) __A, + (__v8si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epu32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __A, + (__v8si) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqd256_mask ((__v8si) __A, + (__v8si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epu64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __A, + (__v2di) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq128_mask ((__v2di) __A, + (__v2di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epu64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __A, + (__v2di) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpeq_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq128_mask ((__v2di) __A, + (__v2di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epu64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __A, + (__v4di) __B, 0, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpeq_epi64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq256_mask ((__v4di) __A, + (__v4di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epu64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __A, + (__v4di) __B, 0, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpeq_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpeqq256_mask ((__v4di) __A, + (__v4di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epu32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __A, + (__v4si) __B, 6, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtd128_mask ((__v4si) __A, + (__v4si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epu32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __A, + (__v4si) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtd128_mask ((__v4si) __A, + (__v4si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epu32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __A, + (__v8si) __B, 6, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtd256_mask ((__v8si) __A, + (__v8si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epu32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __A, + (__v8si) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtd256_mask ((__v8si) __A, + (__v8si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epu64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __A, + (__v2di) __B, 6, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq128_mask ((__v2di) __A, + (__v2di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epu64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __A, + (__v2di) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpgt_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq128_mask ((__v2di) __A, + (__v2di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epu64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __A, + (__v4di) __B, 6, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpgt_epi64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq256_mask ((__v4di) __A, + (__v4di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epu64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __A, + (__v4di) __B, 6, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpgt_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_pcmpgtq256_mask ((__v4di) __A, + (__v4di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_test_epi32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmd128 ((__v4si) __A, + (__v4si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_test_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmd128 ((__v4si) __A, + (__v4si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_test_epi32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestmd256 ((__v8si) __A, + (__v8si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_test_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestmd256 ((__v8si) __A, + (__v8si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_test_epi64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq128 ((__v2di) __A, + (__v2di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_test_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq128 ((__v2di) __A, + (__v2di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_test_epi64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq256 ((__v4di) __A, + (__v4di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_test_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestmq256 ((__v4di) __A, + (__v4di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testn_epi32_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmd128 ((__v4si) __A, + (__v4si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_testn_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmd128 ((__v4si) __A, + (__v4si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testn_epi32_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmd256 ((__v8si) __A, + (__v8si) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_testn_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmd256 ((__v8si) __A, + (__v8si) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testn_epi64_mask (__m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq128 ((__v2di) __A, + (__v2di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_testn_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq128 ((__v2di) __A, + (__v2di) __B, __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testn_epi64_mask (__m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq256 ((__v4di) __A, + (__v4di) __B, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_testn_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__mmask8) __builtin_ia32_ptestnmq256 ((__v4di) __A, + (__v4di) __B, __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m256d __A) +{ + __builtin_ia32_compressstoredf256_mask ((__v4df *) __P, + (__v4df) __A, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m128d __A) +{ + __builtin_ia32_compressstoredf128_mask ((__v2df *) __P, + (__v2df) __A, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m256 __A) +{ + __builtin_ia32_compressstoresf256_mask ((__v8sf *) __P, + (__v8sf) __A, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m128 __A) +{ + __builtin_ia32_compressstoresf128_mask ((__v4sf *) __P, + (__v4sf) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_compressstoredi256_mask ((__v4di *) __P, + (__v4di) __A, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_compressstoredi128_mask ((__v2di *) __P, + (__v2di) __A, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compress_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m256i __A) +{ + __builtin_ia32_compressstoresi256_mask ((__v8si *) __P, + (__v8si) __A, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compress_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m128i __A) +{ + __builtin_ia32_compressstoresi128_mask ((__v4si *) __P, + (__v4si) __A, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_pd (__m256d __W, __mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) +{ + return (__m256d) __builtin_ia32_expanddf256_maskz ((__v4df) __A, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P, + (__v4df) __W, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) +{ + return (__m256d) __builtin_ia32_expandloaddf256_maskz ((__v4df *) __P, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_pd (__m128d __W, __mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_pd (__mmask8 __U, __m128d __A) +{ + return (__m128d) __builtin_ia32_expanddf128_maskz ((__v2df) __A, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P, + (__v2df) __W, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) +{ + return (__m128d) __builtin_ia32_expandloaddf128_maskz ((__v2df *) __P, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_ps (__m256 __W, __mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) +{ + return (__m256) __builtin_ia32_expandsf256_maskz ((__v8sf) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_ps (__m256 __W, __mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) +{ + return (__m256) __builtin_ia32_expandloadsf256_maskz ((__v8sf *) __P, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) + __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_ps (__m128 __W, __mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_ps (__mmask8 __U, __m128 __A) +{ + return (__m128) __builtin_ia32_expandsf128_maskz ((__v4sf) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_ps (__m128 __W, __mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) +{ + return (__m128) __builtin_ia32_expandloadsf128_maskz ((__v4sf *) __P, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_expanddi256_maskz ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U, + void const *__P) +{ + return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P, + (__v4di) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_expandloaddi256_maskz ((__v4di *) __P, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_expanddi128_maskz ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P, + (__v2di) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_expandloaddi128_maskz ((__v2di *) __P, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expand_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_expandsi256_maskz ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U, + void const *__P) +{ + return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P, + (__v8si) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) +{ + return (__m256i) __builtin_ia32_expandloadsi256_maskz ((__v8si *) __P, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expand_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_expandsi128_maskz ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P, + (__v4si) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) +{ + return (__m128i) __builtin_ia32_expandloadsi128_maskz ((__v4si *) __P, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_pd (__m256d __A, __m256i __I, __m256d __B) +{ + return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I + /* idx */ , + (__v4df) __A, + (__v4df) __B, + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_pd (__m256d __A, __mmask8 __U, __m256i __I, + __m256d __B) +{ + return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I + /* idx */ , + (__v4df) __A, + (__v4df) __B, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_pd (__m256d __A, __m256i __I, __mmask8 __U, + __m256d __B) +{ + return (__m256d) __builtin_ia32_vpermi2varpd256_mask ((__v4df) __A, + (__v4di) __I + /* idx */ , + (__v4df) __B, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_pd (__mmask8 __U, __m256d __A, __m256i __I, + __m256d __B) +{ + return (__m256d) __builtin_ia32_vpermt2varpd256_maskz ((__v4di) __I + /* idx */ , + (__v4df) __A, + (__v4df) __B, + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_ps (__m256 __A, __m256i __I, __m256 __B) +{ + return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I + /* idx */ , + (__v8sf) __A, + (__v8sf) __B, + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_ps (__m256 __A, __mmask8 __U, __m256i __I, + __m256 __B) +{ + return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I + /* idx */ , + (__v8sf) __A, + (__v8sf) __B, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_ps (__m256 __A, __m256i __I, __mmask8 __U, + __m256 __B) +{ + return (__m256) __builtin_ia32_vpermi2varps256_mask ((__v8sf) __A, + (__v8si) __I + /* idx */ , + (__v8sf) __B, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_ps (__mmask8 __U, __m256 __A, __m256i __I, + __m256 __B) +{ + return (__m256) __builtin_ia32_vpermt2varps256_maskz ((__v8si) __I + /* idx */ , + (__v8sf) __A, + (__v8sf) __B, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_epi64 (__m128i __A, __m128i __I, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I + /* idx */ , + (__v2di) __A, + (__v2di) __B, + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_epi64 (__m128i __A, __mmask8 __U, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I + /* idx */ , + (__v2di) __A, + (__v2di) __B, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_epi64 (__m128i __A, __m128i __I, __mmask8 __U, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermi2varq128_mask ((__v2di) __A, + (__v2di) __I + /* idx */ , + (__v2di) __B, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_epi64 (__mmask8 __U, __m128i __A, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2varq128_maskz ((__v2di) __I + /* idx */ , + (__v2di) __A, + (__v2di) __B, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_epi32 (__m128i __A, __m128i __I, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I + /* idx */ , + (__v4si) __A, + (__v4si) __B, + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_epi32 (__m128i __A, __mmask8 __U, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I + /* idx */ , + (__v4si) __A, + (__v4si) __B, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_epi32 (__m128i __A, __m128i __I, __mmask8 __U, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermi2vard128_mask ((__v4si) __A, + (__v4si) __I + /* idx */ , + (__v4si) __B, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_epi32 (__mmask8 __U, __m128i __A, __m128i __I, + __m128i __B) +{ + return (__m128i) __builtin_ia32_vpermt2vard128_maskz ((__v4si) __I + /* idx */ , + (__v4si) __A, + (__v4si) __B, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_epi64 (__m256i __A, __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I + /* idx */ , + (__v4di) __A, + (__v4di) __B, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_epi64 (__m256i __A, __mmask8 __U, __m256i __I, + __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I + /* idx */ , + (__v4di) __A, + (__v4di) __B, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_epi64 (__m256i __A, __m256i __I, + __mmask8 __U, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermi2varq256_mask ((__v4di) __A, + (__v4di) __I + /* idx */ , + (__v4di) __B, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_epi64 (__mmask8 __U, __m256i __A, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2varq256_maskz ((__v4di) __I + /* idx */ , + (__v4di) __A, + (__v4di) __B, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex2var_epi32 (__m256i __A, __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I + /* idx */ , + (__v8si) __A, + (__v8si) __B, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex2var_epi32 (__m256i __A, __mmask8 __U, __m256i __I, + __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I + /* idx */ , + (__v8si) __A, + (__v8si) __B, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask2_permutex2var_epi32 (__m256i __A, __m256i __I, + __mmask8 __U, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermi2vard256_mask ((__v8si) __A, + (__v8si) __I + /* idx */ , + (__v8si) __B, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex2var_epi32 (__mmask8 __U, __m256i __A, + __m256i __I, __m256i __B) +{ + return (__m256i) __builtin_ia32_vpermt2vard256_maskz ((__v8si) __I + /* idx */ , + (__v8si) __A, + (__v8si) __B, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_pd (__m128d __A, __m128i __I, __m128d __B) +{ + return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I + /* idx */ , + (__v2df) __A, + (__v2df) __B, + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_pd (__m128d __A, __mmask8 __U, __m128i __I, + __m128d __B) +{ + return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I + /* idx */ , + (__v2df) __A, + (__v2df) __B, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_pd (__m128d __A, __m128i __I, __mmask8 __U, + __m128d __B) +{ + return (__m128d) __builtin_ia32_vpermi2varpd128_mask ((__v2df) __A, + (__v2di) __I + /* idx */ , + (__v2df) __B, + (__mmask8) + __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_pd (__mmask8 __U, __m128d __A, __m128i __I, + __m128d __B) +{ + return (__m128d) __builtin_ia32_vpermt2varpd128_maskz ((__v2di) __I + /* idx */ , + (__v2df) __A, + (__v2df) __B, + (__mmask8) + __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutex2var_ps (__m128 __A, __m128i __I, __m128 __B) +{ + return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I + /* idx */ , + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutex2var_ps (__m128 __A, __mmask8 __U, __m128i __I, + __m128 __B) +{ + return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I + /* idx */ , + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask2_permutex2var_ps (__m128 __A, __m128i __I, __mmask8 __U, + __m128 __B) +{ + return (__m128) __builtin_ia32_vpermi2varps128_mask ((__v4sf) __A, + (__v4si) __I + /* idx */ , + (__v4sf) __B, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutex2var_ps (__mmask8 __U, __m128 __A, __m128i __I, + __m128 __B) +{ + return (__m128) __builtin_ia32_vpermt2varps128_maskz ((__v4si) __I + /* idx */ , + (__v4sf) __A, + (__v4sf) __B, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srav_epi64 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srav_epi64 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srav_epi64 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sllv_epi32 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sllv_epi32 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sllv_epi32 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sllv_epi32 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sllv_epi64 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv4di_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sllv_epi64 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psllv4di_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sllv_epi64 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv2di_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sllv_epi64 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psllv2di_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srav_epi32 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrav8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srav_epi32 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrav8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srav_epi32 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrav4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srav_epi32 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrav4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srlv_epi32 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srlv_epi32 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv8si_mask ((__v8si) __X, + (__v8si) __Y, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srlv_epi32 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srlv_epi32 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv4si_mask ((__v4si) __X, + (__v4si) __Y, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srlv_epi64 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv4di_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srlv_epi64 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psrlv4di_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srlv_epi64 (__m128i __W, __mmask8 __U, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv2di_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srlv_epi64 (__mmask8 __U, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psrlv2di_mask ((__v2di) __X, + (__v2di) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rolv_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rolv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rolv_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rolv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rorv_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rorv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rorv_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rorv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rolv_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rolv_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rolv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rorv_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rorv_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rorv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srav_epi64 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srav_epi64 (__m256i __W, __mmask8 __U, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X, + (__v4di) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_and_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pandq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_and_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pandq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_pd (), + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_and_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pandq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_and_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pandq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_pd (), + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_andnot_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pandnq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_andnot_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pandnq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_pd (), + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_andnot_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pandnq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_andnot_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pandnq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_pd (), + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_or_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_porq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_or_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_porq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_or_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A | (__v4du)__B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_or_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_porq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_or_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_porq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A | (__v2du)__B); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_xor_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pxorq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_xor_epi64 (__mmask8 __U, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pxorq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_xor_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) ((__v4du)__A ^ (__v4du)__B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_xor_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pxorq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_xor_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pxorq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A ^ (__v2du)__B); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_div_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_div_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_div_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_div_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_div_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_div_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mul_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mul_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mul_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mul_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epi64 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epi64 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epi64 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epi64 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epu64 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_epu64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_epu64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epu64 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epu64 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epi32 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epi32 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epi32 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epi32 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_max_epu32 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_max_epu32 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_min_epu32 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_min_epu32 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epi64 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epi64 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epi64 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epi64 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epu64 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epu64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epu64 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epu64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epu64 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epu64 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epi32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epi32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epi32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epi32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_max_epu32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_max_epu32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_min_epu32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_min_epu32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, __M); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_unpcklpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_unpcklpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_unpcklpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_unpcklpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpacklo_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B) +{ + return (__m256) __builtin_ia32_unpcklps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B) +{ + return (__m256d) __builtin_ia32_unpckhpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_pd (__mmask8 __U, __m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_unpckhpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B) +{ + return (__m128d) __builtin_ia32_unpckhpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_pd (__mmask8 __U, __m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_unpckhpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_unpackhi_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B) +{ + return (__m256) __builtin_ia32_unpckhps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpackhi_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_unpckhps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpackhi_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpckhps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpackhi_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpckhps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtph_ps (__m128 __W, __mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtph_ps (__mmask8 __U, __m128i __A) +{ + return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_unpacklo_ps (__mmask8 __U, __m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_unpcklps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtph_ps (__m256 __W, __mmask8 __U, __m128i __A) +{ + return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A) +{ + return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_unpacklo_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpcklps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_unpacklo_ps (__mmask8 __U, __m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpcklps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sra_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psrad256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sra_epi32 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psrad256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sra_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psrad128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sra_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psrad128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sra_epi64 (__m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sra_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sra_epi64 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sra_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sra_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sra_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sll_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pslld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sll_epi32 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pslld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_sll_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_psllq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_sll_epi64 (__mmask8 __U, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_psllq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sll_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_pslld256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sll_epi32 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_pslld256_mask ((__v8si) __A, + (__v4si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_sll_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B) +{ + return (__m256i) __builtin_ia32_psllq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_sll_epi64 (__mmask8 __U, __m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_psllq256_mask ((__v4di) __A, + (__v2di) __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_ps (__m256 __W, __mmask8 __U, __m256i __X, + __m256 __Y) +{ + return (__m256) __builtin_ia32_permvarsf256_mask ((__v8sf) __Y, + (__v8si) __X, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_ps (__mmask8 __U, __m256i __X, __m256 __Y) +{ + return (__m256) __builtin_ia32_permvarsf256_mask ((__v8sf) __Y, + (__v8si) __X, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_pd (__m256i __X, __m256d __Y) +{ + return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y, + (__v4di) __X, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_pd (__m256d __W, __mmask8 __U, __m256i __X, + __m256d __Y) +{ + return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y, + (__v4di) __X, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_pd (__mmask8 __U, __m256i __X, __m256d __Y) +{ + return (__m256d) __builtin_ia32_permvardf256_mask ((__v4df) __Y, + (__v4di) __X, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutevar_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256i __C) +{ + return (__m256d) __builtin_ia32_vpermilvarpd256_mask ((__v4df) __A, + (__v4di) __C, + (__v4df) __W, + (__mmask8) + __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutevar_pd (__mmask8 __U, __m256d __A, __m256i __C) +{ + return (__m256d) __builtin_ia32_vpermilvarpd256_mask ((__v4df) __A, + (__v4di) __C, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutevar_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256i __C) +{ + return (__m256) __builtin_ia32_vpermilvarps256_mask ((__v8sf) __A, + (__v8si) __C, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutevar_ps (__mmask8 __U, __m256 __A, __m256i __C) +{ + return (__m256) __builtin_ia32_vpermilvarps256_mask ((__v8sf) __A, + (__v8si) __C, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutevar_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128i __C) +{ + return (__m128d) __builtin_ia32_vpermilvarpd_mask ((__v2df) __A, + (__v2di) __C, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutevar_pd (__mmask8 __U, __m128d __A, __m128i __C) +{ + return (__m128d) __builtin_ia32_vpermilvarpd_mask ((__v2df) __A, + (__v2di) __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permutevar_ps (__m128 __W, __mmask8 __U, __m128 __A, + __m128i __C) +{ + return (__m128) __builtin_ia32_vpermilvarps_mask ((__v4sf) __A, + (__v4si) __C, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permutevar_ps (__mmask8 __U, __m128 __A, __m128i __C) +{ + return (__m128) __builtin_ia32_vpermilvarps_mask ((__v4sf) __A, + (__v4si) __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mullo_epi32 (__mmask8 __M, __m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_epi64 (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y, + (__v4di) __X, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mullo_epi32 (__m256i __W, __mmask8 __M, __m256i __A, + __m256i __B) +{ + return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mullo_epi32 (__mmask8 __M, __m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mullo_epi32 (__m128i __W, __mmask8 __M, __m128i __A, + __m128i __B) +{ + return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mul_epi32 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X, + (__v8si) __Y, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mul_epi32 (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X, + (__v8si) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_epi32 (__m128i __W, __mmask8 __M, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X, + (__v4si) __Y, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X, + (__v4si) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_epi64 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y, + (__v4di) __X, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_epi64 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y, + (__v4di) __X, + (__v4di) __W, + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_mul_epu32 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X, + (__v8si) __Y, + (__v4di) __W, __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutexvar_epi32 (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y, + (__v8si) __X, + (__v8si) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_mul_epu32 (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X, + (__v8si) __Y, + (__v4di) + _mm256_avx512_setzero_si256 (), + __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_mul_epu32 (__m128i __W, __mmask8 __M, __m128i __X, + __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X, + (__v4si) __Y, + (__v2di) __W, __M); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_mul_epu32 (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X, + (__v4si) __Y, + (__v2di) + _mm_avx512_setzero_si128 (), + __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutexvar_epi32 (__m256i __X, __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y, + (__v8si) __X, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutexvar_epi32 (__m256i __W, __mmask8 __M, __m256i __X, + __m256i __Y) +{ + return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y, + (__v8si) __X, + (__v8si) __W, + __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epu32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epu32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epu32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epu32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epu32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epu32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epu32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epu32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epu64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epu64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epu64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epu64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epu64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epu64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epu64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epu64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epi32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epi32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epi32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epi32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epi32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epi32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epi32_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epi32_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpneq_epi64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpneq_epi64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmplt_epi64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmplt_epi64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmpge_epi64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmpge_epi64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmple_epi64_mask (__mmask8 __M, __m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmple_epi64_mask (__m256i __X, __m256i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epu32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epu32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epu32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epu32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epu32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epu32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epu32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epu32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epu64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epu64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epu64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epu64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epu64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epu64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epu64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epu64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epi32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epi32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epi32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epi32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epi32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epi32_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epi32_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, 2, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpneq_epi64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 4, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_epi64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 4, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmplt_epi64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 1, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 1, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmpge_epi64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 5, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_epi64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 5, + (__mmask8) -1); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmple_epi64_mask (__mmask8 __M, __m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 2, + (__mmask8) __M); +} + +extern __inline __mmask8 + __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_epi64_mask (__m128i __X, __m128i __Y) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, 2, + (__mmask8) -1); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex_epi64 (__m256i __X, const int __I) +{ + return (__m256i) __builtin_ia32_permdi256_mask ((__v4di) __X, + __I, + (__v4di) + _mm256_avx512_setzero_si256(), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex_epi64 (__m256i __W, __mmask8 __M, + __m256i __X, const int __I) +{ + return (__m256i) __builtin_ia32_permdi256_mask ((__v4di) __X, + __I, + (__v4di) __W, + (__mmask8) __M); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex_epi64 (__mmask8 __M, __m256i __X, const int __I) +{ + return (__m256i) __builtin_ia32_permdi256_mask ((__v4di) __X, + __I, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __M); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_pd (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B, const int __imm) +{ + return (__m256d) __builtin_ia32_shufpd256_mask ((__v4df) __A, + (__v4df) __B, __imm, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_pd (__mmask8 __U, __m256d __A, __m256d __B, + const int __imm) +{ + return (__m256d) __builtin_ia32_shufpd256_mask ((__v4df) __A, + (__v4df) __B, __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shuffle_pd (__m128d __W, __mmask8 __U, __m128d __A, + __m128d __B, const int __imm) +{ + return (__m128d) __builtin_ia32_shufpd128_mask ((__v2df) __A, + (__v2df) __B, __imm, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shuffle_pd (__mmask8 __U, __m128d __A, __m128d __B, + const int __imm) +{ + return (__m128d) __builtin_ia32_shufpd128_mask ((__v2df) __A, + (__v2df) __B, __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_ps (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B, const int __imm) +{ + return (__m256) __builtin_ia32_shufps256_mask ((__v8sf) __A, + (__v8sf) __B, __imm, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_ps (__mmask8 __U, __m256 __A, __m256 __B, + const int __imm) +{ + return (__m256) __builtin_ia32_shufps256_mask ((__v8sf) __A, + (__v8sf) __B, __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shuffle_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B, + const int __imm) +{ + return (__m128) __builtin_ia32_shufps128_mask ((__v4sf) __A, + (__v4sf) __B, __imm, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shuffle_ps (__mmask8 __U, __m128 __A, __m128 __B, + const int __imm) +{ + return (__m128) __builtin_ia32_shufps128_mask ((__v4sf) __A, + (__v4sf) __B, __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_inserti32x4 (__m256i __A, __m128i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si) __A, + (__v4si) __B, + __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_inserti32x4 (__m256i __W, __mmask8 __U, __m256i __A, + __m128i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si) __A, + (__v4si) __B, + __imm, + (__v8si) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_inserti32x4 (__mmask8 __U, __m256i __A, __m128i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si) __A, + (__v4si) __B, + __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insertf32x4 (__m256 __A, __m128 __B, const int __imm) +{ + return (__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf) __A, + (__v4sf) __B, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_insertf32x4 (__m256 __W, __mmask8 __U, __m256 __A, + __m128 __B, const int __imm) +{ + return (__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf) __A, + (__v4sf) __B, + __imm, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_insertf32x4 (__mmask8 __U, __m256 __A, __m128 __B, + const int __imm) +{ + return (__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf) __A, + (__v4sf) __B, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extracti32x4_epi32 (__m256i __A, const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si) __A, + __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_extracti32x4_epi32 (__m128i __W, __mmask8 __U, __m256i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si) __A, + __imm, + (__v4si) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_extracti32x4_epi32 (__mmask8 __U, __m256i __A, + const int __imm) +{ + return (__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si) __A, + __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extractf32x4_ps (__m256 __A, const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf) __A, + __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_extractf32x4_ps (__m128 __W, __mmask8 __U, __m256 __A, + const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf) __A, + __imm, + (__v4sf) __W, + (__mmask8) + __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_extractf32x4_ps (__mmask8 __U, __m256 __A, + const int __imm) +{ + return (__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf) __A, + __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_i64x2 (__m256i __A, __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di) __A, + (__v4di) __B, + __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_i64x2 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di) __A, + (__v4di) __B, + __imm, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_i64x2 (__mmask8 __U, __m256i __A, __m256i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di) __A, + (__v4di) __B, + __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_i32x4 (__m256i __A, __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si) __A, + (__v8si) __B, + __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_i32x4 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si) __A, + (__v8si) __B, + __imm, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_i32x4 (__mmask8 __U, __m256i __A, __m256i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si) __A, + (__v8si) __B, + __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_f64x2 (__m256d __A, __m256d __B, const int __imm) +{ + return (__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df) __A, + (__v4df) __B, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_f64x2 (__m256d __W, __mmask8 __U, __m256d __A, + __m256d __B, const int __imm) +{ + return (__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df) __A, + (__v4df) __B, + __imm, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_f64x2 (__mmask8 __U, __m256d __A, __m256d __B, + const int __imm) +{ + return (__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df) __A, + (__v4df) __B, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_f32x4 (__m256 __A, __m256 __B, const int __imm) +{ + return (__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf) __A, + (__v8sf) __B, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_f32x4 (__m256 __W, __mmask8 __U, __m256 __A, + __m256 __B, const int __imm) +{ + return (__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf) __A, + (__v8sf) __B, + __imm, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_f32x4 (__mmask8 __U, __m256 __A, __m256 __B, + const int __imm) +{ + return (__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf) __A, + (__v8sf) __B, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fixupimm_pd (__m256d __A, __m256d __B, __m256i __C, + const int __imm) +{ + return (__m256d) __builtin_ia32_fixupimmpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4di) __C, + __imm, + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fixupimm_pd (__m256d __A, __mmask8 __U, __m256d __B, + __m256i __C, const int __imm) +{ + return (__m256d) __builtin_ia32_fixupimmpd256_mask ((__v4df) __A, + (__v4df) __B, + (__v4di) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fixupimm_pd (__mmask8 __U, __m256d __A, __m256d __B, + __m256i __C, const int __imm) +{ + return (__m256d) __builtin_ia32_fixupimmpd256_maskz ((__v4df) __A, + (__v4df) __B, + (__v4di) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fixupimm_ps (__m256 __A, __m256 __B, __m256i __C, + const int __imm) +{ + return (__m256) __builtin_ia32_fixupimmps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8si) __C, + __imm, + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_fixupimm_ps (__m256 __A, __mmask8 __U, __m256 __B, + __m256i __C, const int __imm) +{ + return (__m256) __builtin_ia32_fixupimmps256_mask ((__v8sf) __A, + (__v8sf) __B, + (__v8si) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_fixupimm_ps (__mmask8 __U, __m256 __A, __m256 __B, + __m256i __C, const int __imm) +{ + return (__m256) __builtin_ia32_fixupimmps256_maskz ((__v8sf) __A, + (__v8sf) __B, + (__v8si) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_pd (__m128d __A, __m128d __B, __m128i __C, + const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, + __imm, + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_pd (__m128d __A, __mmask8 __U, __m128d __B, + __m128i __C, const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmpd128_mask ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_pd (__mmask8 __U, __m128d __A, __m128d __B, + __m128i __C, const int __imm) +{ + return (__m128d) __builtin_ia32_fixupimmpd128_maskz ((__v2df) __A, + (__v2df) __B, + (__v2di) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fixupimm_ps (__m128 __A, __m128 __B, __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, + __imm, + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_fixupimm_ps (__m128 __A, __mmask8 __U, __m128 __B, + __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmps128_mask ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_fixupimm_ps (__mmask8 __U, __m128 __A, __m128 __B, + __m128i __C, const int __imm) +{ + return (__m128) __builtin_ia32_fixupimmps128_maskz ((__v4sf) __A, + (__v4sf) __B, + (__v4si) __C, + __imm, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srli_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrldi256_mask ((__v8si) __A, __imm, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srli_epi32 (__mmask8 __U, __m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrldi256_mask ((__v8si) __A, __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srli_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrldi128_mask ((__v4si) __A, __imm, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srli_epi32 (__mmask8 __U, __m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrldi128_mask ((__v4si) __A, __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srli_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrlqi256_mask ((__v4di) __A, __imm, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srli_epi64 (__mmask8 __U, __m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psrlqi256_mask ((__v4di) __A, __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srli_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrlqi128_mask ((__v2di) __A, __imm, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srli_epi64 (__mmask8 __U, __m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psrlqi128_mask ((__v2di) __A, __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_ternarylogic_epi64 (__m256i __A, __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __C, + (unsigned char) __imm, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_ternarylogic_epi64 (__m256i __A, __mmask8 __U, + __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogq256_mask ((__v4di) __A, + (__v4di) __B, + (__v4di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_ternarylogic_epi64 (__mmask8 __U, __m256i __A, + __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogq256_maskz ((__v4di) __A, + (__v4di) __B, + (__v4di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_ternarylogic_epi32 (__m256i __A, __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __C, + (unsigned char) __imm, + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_ternarylogic_epi32 (__m256i __A, __mmask8 __U, + __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogd256_mask ((__v8si) __A, + (__v8si) __B, + (__v8si) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_ternarylogic_epi32 (__mmask8 __U, __m256i __A, + __m256i __B, __m256i __C, + const int __imm) +{ + return (__m256i) + __builtin_ia32_pternlogd256_maskz ((__v8si) __A, + (__v8si) __B, + (__v8si) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ternarylogic_epi64 (__m128i __A, __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __C, + (unsigned char) __imm, + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_ternarylogic_epi64 (__m128i __A, __mmask8 __U, + __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogq128_mask ((__v2di) __A, + (__v2di) __B, + (__v2di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_ternarylogic_epi64 (__mmask8 __U, __m128i __A, + __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogq128_maskz ((__v2di) __A, + (__v2di) __B, + (__v2di) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ternarylogic_epi32 (__m128i __A, __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __C, + (unsigned char) __imm, + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_ternarylogic_epi32 (__m128i __A, __mmask8 __U, + __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogd128_mask ((__v4si) __A, + (__v4si) __B, + (__v4si) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_ternarylogic_epi32 (__mmask8 __U, __m128i __A, + __m128i __B, __m128i __C, + const int __imm) +{ + return (__m128i) + __builtin_ia32_pternlogd128_maskz ((__v4si) __A, + (__v4si) __B, + (__v4si) __C, + (unsigned char) __imm, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_roundscale_ps (__m256 __A, const int __imm) +{ + return (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_roundscale_ps (__m256 __W, __mmask8 __U, __m256 __A, + const int __imm) +{ + return (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A, + __imm, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_roundscale_ps (__mmask8 __U, __m256 __A, const int __imm) +{ + return (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A, + __imm, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_roundscale_pd (__m256d __A, const int __imm) +{ + return (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_roundscale_pd (__m256d __W, __mmask8 __U, __m256d __A, + const int __imm) +{ + return (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, + __imm, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_roundscale_pd (__mmask8 __U, __m256d __A, const int __imm) +{ + return (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, + __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_ps (__m128 __A, const int __imm) +{ + return (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, + __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_ps (__m128 __W, __mmask8 __U, __m128 __A, + const int __imm) +{ + return (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, + __imm, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_ps (__mmask8 __U, __m128 __A, const int __imm) +{ + return (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, + __imm, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roundscale_pd (__m128d __A, const int __imm) +{ + return (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, + __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_roundscale_pd (__m128d __W, __mmask8 __U, __m128d __A, + const int __imm) +{ + return (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, + __imm, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_roundscale_pd (__mmask8 __U, __m128d __A, const int __imm) +{ + return (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, + __imm, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getmant_ps (__m256 __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256) __builtin_ia32_getmantps256_mask ((__v8sf) __A, + (__C << 2) | __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getmant_ps (__m256 __W, __mmask8 __U, __m256 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256) __builtin_ia32_getmantps256_mask ((__v8sf) __A, + (__C << 2) | __B, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getmant_ps (__mmask8 __U, __m256 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256) __builtin_ia32_getmantps256_mask ((__v8sf) __A, + (__C << 2) | __B, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_ps (__m128 __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128) __builtin_ia32_getmantps128_mask ((__v4sf) __A, + (__C << 2) | __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) -1); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_ps (__m128 __W, __mmask8 __U, __m128 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128) __builtin_ia32_getmantps128_mask ((__v4sf) __A, + (__C << 2) | __B, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_ps (__mmask8 __U, __m128 __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128) __builtin_ia32_getmantps128_mask ((__v4sf) __A, + (__C << 2) | __B, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_getmant_pd (__m256d __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256d) __builtin_ia32_getmantpd256_mask ((__v4df) __A, + (__C << 2) | __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_getmant_pd (__m256d __W, __mmask8 __U, __m256d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256d) __builtin_ia32_getmantpd256_mask ((__v4df) __A, + (__C << 2) | __B, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_getmant_pd (__mmask8 __U, __m256d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m256d) __builtin_ia32_getmantpd256_mask ((__v4df) __A, + (__C << 2) | __B, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getmant_pd (__m128d __A, _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128d) __builtin_ia32_getmantpd128_mask ((__v2df) __A, + (__C << 2) | __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) -1); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_getmant_pd (__m128d __W, __mmask8 __U, __m128d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128d) __builtin_ia32_getmantpd128_mask ((__v2df) __A, + (__C << 2) | __B, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_getmant_pd (__mmask8 __U, __m128d __A, + _MM_MANTISSA_NORM_ENUM __B, + _MM_MANTISSA_SIGN_ENUM __C) +{ + return (__m128d) __builtin_ia32_getmantpd128_mask ((__v2df) __A, + (__C << 2) | __B, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i32gather_ps (__m256 __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m256) __builtin_ia32_gather3siv8sf ((__v8sf) __v1_old, + __addr, + (__v8si) __index, + __mask, __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i32gather_ps (__m128 __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128) __builtin_ia32_gather3siv4sf ((__v4sf) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i32gather_pd (__m256d __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m256d) __builtin_ia32_gather3siv4df ((__v4df) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i32gather_pd (__m128d __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128d) __builtin_ia32_gather3siv2df ((__v2df) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i64gather_ps (__m128 __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m128) __builtin_ia32_gather3div8sf ((__v4sf) __v1_old, + __addr, + (__v4di) __index, + __mask, __scale); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i64gather_ps (__m128 __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128) __builtin_ia32_gather3div4sf ((__v4sf) __v1_old, + __addr, + (__v2di) __index, + __mask, __scale); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i64gather_pd (__m256d __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m256d) __builtin_ia32_gather3div4df ((__v4df) __v1_old, + __addr, + (__v4di) __index, + __mask, __scale); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i64gather_pd (__m128d __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128d) __builtin_ia32_gather3div2df ((__v2df) __v1_old, + __addr, + (__v2di) __index, + __mask, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i32gather_epi32 (__m256i __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m256i) __builtin_ia32_gather3siv8si ((__v8si) __v1_old, + __addr, + (__v8si) __index, + __mask, __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i32gather_epi32 (__m128i __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128i) __builtin_ia32_gather3siv4si ((__v4si) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i32gather_epi64 (__m256i __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m256i) __builtin_ia32_gather3siv4di ((__v4di) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i32gather_epi64 (__m128i __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128i) __builtin_ia32_gather3siv2di ((__v2di) __v1_old, + __addr, + (__v4si) __index, + __mask, __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i64gather_epi32 (__m128i __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m128i) __builtin_ia32_gather3div8si ((__v4si) __v1_old, + __addr, + (__v4di) __index, + __mask, __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i64gather_epi32 (__m128i __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128i) __builtin_ia32_gather3div4si ((__v4si) __v1_old, + __addr, + (__v2di) __index, + __mask, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mmask_i64gather_epi64 (__m256i __v1_old, __mmask8 __mask, + __m256i __index, void const *__addr, + int __scale) +{ + return (__m256i) __builtin_ia32_gather3div4di ((__v4di) __v1_old, + __addr, + (__v4di) __index, + __mask, __scale); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mmask_i64gather_epi64 (__m128i __v1_old, __mmask8 __mask, + __m128i __index, void const *__addr, + int __scale) +{ + return (__m128i) __builtin_ia32_gather3div2di ((__v2di) __v1_old, + __addr, + (__v2di) __index, + __mask, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32scatter_ps (void *__addr, __m256i __index, + __m256 __v1, const int __scale) +{ + __builtin_ia32_scattersiv8sf (__addr, (__mmask8) 0xFF, + (__v8si) __index, (__v8sf) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32scatter_ps (void *__addr, __mmask8 __mask, + __m256i __index, __m256 __v1, + const int __scale) +{ + __builtin_ia32_scattersiv8sf (__addr, __mask, (__v8si) __index, + (__v8sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32scatter_ps (void *__addr, __m128i __index, __m128 __v1, + const int __scale) +{ + __builtin_ia32_scattersiv4sf (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v4sf) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32scatter_ps (void *__addr, __mmask8 __mask, + __m128i __index, __m128 __v1, + const int __scale) +{ + __builtin_ia32_scattersiv4sf (__addr, __mask, (__v4si) __index, + (__v4sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32scatter_pd (void *__addr, __m128i __index, + __m256d __v1, const int __scale) +{ + __builtin_ia32_scattersiv4df (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v4df) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32scatter_pd (void *__addr, __mmask8 __mask, + __m128i __index, __m256d __v1, + const int __scale) +{ + __builtin_ia32_scattersiv4df (__addr, __mask, (__v4si) __index, + (__v4df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32scatter_pd (void *__addr, __m128i __index, + __m128d __v1, const int __scale) +{ + __builtin_ia32_scattersiv2df (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v2df) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32scatter_pd (void *__addr, __mmask8 __mask, + __m128i __index, __m128d __v1, + const int __scale) +{ + __builtin_ia32_scattersiv2df (__addr, __mask, (__v4si) __index, + (__v2df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64scatter_ps (void *__addr, __m256i __index, + __m128 __v1, const int __scale) +{ + __builtin_ia32_scatterdiv8sf (__addr, (__mmask8) 0xFF, + (__v4di) __index, (__v4sf) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64scatter_ps (void *__addr, __mmask8 __mask, + __m256i __index, __m128 __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv8sf (__addr, __mask, (__v4di) __index, + (__v4sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64scatter_ps (void *__addr, __m128i __index, __m128 __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv4sf (__addr, (__mmask8) 0xFF, + (__v2di) __index, (__v4sf) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64scatter_ps (void *__addr, __mmask8 __mask, + __m128i __index, __m128 __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv4sf (__addr, __mask, (__v2di) __index, + (__v4sf) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64scatter_pd (void *__addr, __m256i __index, + __m256d __v1, const int __scale) +{ + __builtin_ia32_scatterdiv4df (__addr, (__mmask8) 0xFF, + (__v4di) __index, (__v4df) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64scatter_pd (void *__addr, __mmask8 __mask, + __m256i __index, __m256d __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv4df (__addr, __mask, (__v4di) __index, + (__v4df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64scatter_pd (void *__addr, __m128i __index, + __m128d __v1, const int __scale) +{ + __builtin_ia32_scatterdiv2df (__addr, (__mmask8) 0xFF, + (__v2di) __index, (__v2df) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64scatter_pd (void *__addr, __mmask8 __mask, + __m128i __index, __m128d __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv2df (__addr, __mask, (__v2di) __index, + (__v2df) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32scatter_epi32 (void *__addr, __m256i __index, + __m256i __v1, const int __scale) +{ + __builtin_ia32_scattersiv8si (__addr, (__mmask8) 0xFF, + (__v8si) __index, (__v8si) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32scatter_epi32 (void *__addr, __mmask8 __mask, + __m256i __index, __m256i __v1, + const int __scale) +{ + __builtin_ia32_scattersiv8si (__addr, __mask, (__v8si) __index, + (__v8si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32scatter_epi32 (void *__addr, __m128i __index, + __m128i __v1, const int __scale) +{ + __builtin_ia32_scattersiv4si (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v4si) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32scatter_epi32 (void *__addr, __mmask8 __mask, + __m128i __index, __m128i __v1, + const int __scale) +{ + __builtin_ia32_scattersiv4si (__addr, __mask, (__v4si) __index, + (__v4si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i32scatter_epi64 (void *__addr, __m128i __index, + __m256i __v1, const int __scale) +{ + __builtin_ia32_scattersiv4di (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v4di) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i32scatter_epi64 (void *__addr, __mmask8 __mask, + __m128i __index, __m256i __v1, + const int __scale) +{ + __builtin_ia32_scattersiv4di (__addr, __mask, (__v4si) __index, + (__v4di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i32scatter_epi64 (void *__addr, __m128i __index, + __m128i __v1, const int __scale) +{ + __builtin_ia32_scattersiv2di (__addr, (__mmask8) 0xFF, + (__v4si) __index, (__v2di) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i32scatter_epi64 (void *__addr, __mmask8 __mask, + __m128i __index, __m128i __v1, + const int __scale) +{ + __builtin_ia32_scattersiv2di (__addr, __mask, (__v4si) __index, + (__v2di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64scatter_epi32 (void *__addr, __m256i __index, + __m128i __v1, const int __scale) +{ + __builtin_ia32_scatterdiv8si (__addr, (__mmask8) 0xFF, + (__v4di) __index, (__v4si) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64scatter_epi32 (void *__addr, __mmask8 __mask, + __m256i __index, __m128i __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv8si (__addr, __mask, (__v4di) __index, + (__v4si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64scatter_epi32 (void *__addr, __m128i __index, + __m128i __v1, const int __scale) +{ + __builtin_ia32_scatterdiv4si (__addr, (__mmask8) 0xFF, + (__v2di) __index, (__v4si) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64scatter_epi32 (void *__addr, __mmask8 __mask, + __m128i __index, __m128i __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv4si (__addr, __mask, (__v2di) __index, + (__v4si) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_i64scatter_epi64 (void *__addr, __m256i __index, + __m256i __v1, const int __scale) +{ + __builtin_ia32_scatterdiv4di (__addr, (__mmask8) 0xFF, + (__v4di) __index, (__v4di) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_i64scatter_epi64 (void *__addr, __mmask8 __mask, + __m256i __index, __m256i __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv4di (__addr, __mask, (__v4di) __index, + (__v4di) __v1, __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_i64scatter_epi64 (void *__addr, __m128i __index, + __m128i __v1, const int __scale) +{ + __builtin_ia32_scatterdiv2di (__addr, (__mmask8) 0xFF, + (__v2di) __index, (__v2di) __v1, + __scale); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_i64scatter_epi64 (void *__addr, __mmask8 __mask, + __m128i __index, __m128i __v1, + const int __scale) +{ + __builtin_ia32_scatterdiv2di (__addr, __mask, (__v2di) __index, + (__v2di) __v1, __scale); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_shuffle_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + _MM_PERM_ENUM __mask) +{ + return (__m256i) __builtin_ia32_pshufd256_mask ((__v8si) __A, __mask, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_shuffle_epi32 (__mmask8 __U, __m256i __A, + _MM_PERM_ENUM __mask) +{ + return (__m256i) __builtin_ia32_pshufd256_mask ((__v8si) __A, __mask, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_shuffle_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + _MM_PERM_ENUM __mask) +{ + return (__m128i) __builtin_ia32_pshufd128_mask ((__v4si) __A, __mask, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_shuffle_epi32 (__mmask8 __U, __m128i __A, + _MM_PERM_ENUM __mask) +{ + return (__m128i) __builtin_ia32_pshufd128_mask ((__v4si) __A, __mask, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rol_epi32 (__m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prold256_mask ((__v8si) __A, __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rol_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + const int __B) +{ + return (__m256i) __builtin_ia32_prold256_mask ((__v8si) __A, __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rol_epi32 (__mmask8 __U, __m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prold256_mask ((__v8si) __A, __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rol_epi32 (__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prold128_mask ((__v4si) __A, __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rol_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + const int __B) +{ + return (__m128i) __builtin_ia32_prold128_mask ((__v4si) __A, __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rol_epi32 (__mmask8 __U, __m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prold128_mask ((__v4si) __A, __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_ror_epi32 (__m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prord256_mask ((__v8si) __A, __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_ror_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + const int __B) +{ + return (__m256i) __builtin_ia32_prord256_mask ((__v8si) __A, __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_ror_epi32 (__mmask8 __U, __m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prord256_mask ((__v8si) __A, __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ror_epi32 (__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prord128_mask ((__v4si) __A, __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_ror_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + const int __B) +{ + return (__m128i) __builtin_ia32_prord128_mask ((__v4si) __A, __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_ror_epi32 (__mmask8 __U, __m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prord128_mask ((__v4si) __A, __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rol_epi64 (__m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prolq256_mask ((__v4di) __A, __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_rol_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + const int __B) +{ + return (__m256i) __builtin_ia32_prolq256_mask ((__v4di) __A, __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_rol_epi64 (__mmask8 __U, __m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prolq256_mask ((__v4di) __A, __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rol_epi64 (__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prolq128_mask ((__v2di) __A, __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_rol_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + const int __B) +{ + return (__m128i) __builtin_ia32_prolq128_mask ((__v2di) __A, __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_rol_epi64 (__mmask8 __U, __m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prolq128_mask ((__v2di) __A, __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_ror_epi64 (__m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prorq256_mask ((__v4di) __A, __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_ror_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + const int __B) +{ + return (__m256i) __builtin_ia32_prorq256_mask ((__v4di) __A, __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_ror_epi64 (__mmask8 __U, __m256i __A, const int __B) +{ + return (__m256i) __builtin_ia32_prorq256_mask ((__v4di) __A, __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ror_epi64 (__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prorq128_mask ((__v2di) __A, __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_ror_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + const int __B) +{ + return (__m128i) __builtin_ia32_prorq128_mask ((__v2di) __A, __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_ror_epi64 (__mmask8 __U, __m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_prorq128_mask ((__v2di) __A, __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_alignr_epi32 (__m128i __A, __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_alignd128_mask ((__v4si) __A, + (__v4si) __B, __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_alignr_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_alignd128_mask ((__v4si) __A, + (__v4si) __B, __imm, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_alignr_epi32 (__mmask8 __U, __m128i __A, __m128i __B, + const int __imm) +{ + return (__m128i) __builtin_ia32_alignd128_mask ((__v4si) __A, + (__v4si) __B, __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_alignr_epi64 (__m128i __A, __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_alignq128_mask ((__v2di) __A, + (__v2di) __B, __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_alignr_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + __m128i __B, const int __imm) +{ + return (__m128i) __builtin_ia32_alignq128_mask ((__v2di) __A, + (__v2di) __B, __imm, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_alignr_epi64 (__mmask8 __U, __m128i __A, __m128i __B, + const int __imm) +{ + return (__m128i) __builtin_ia32_alignq128_mask ((__v2di) __A, + (__v2di) __B, __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_alignr_epi32 (__m256i __A, __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_alignd256_mask ((__v8si) __A, + (__v8si) __B, __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_alignr_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_alignd256_mask ((__v8si) __A, + (__v8si) __B, __imm, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_alignr_epi32 (__mmask8 __U, __m256i __A, __m256i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_alignd256_mask ((__v8si) __A, + (__v8si) __B, __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_alignr_epi64 (__m256i __A, __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_alignq256_mask ((__v4di) __A, + (__v4di) __B, __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_alignr_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + __m256i __B, const int __imm) +{ + return (__m256i) __builtin_ia32_alignq256_mask ((__v4di) __A, + (__v4di) __B, __imm, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_alignr_epi64 (__mmask8 __U, __m256i __A, __m256i __B, + const int __imm) +{ + return (__m256i) __builtin_ia32_alignq256_mask ((__v4di) __A, + (__v4di) __B, __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m128 __A, + const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, __I, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_cvtps_ph (__mmask8 __U, __m128 __A, const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, __I, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m256 __A, + const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, __I, + (__v8hi) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_cvtps_ph (__mmask8 __U, __m256 __A, const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, __I, + (__v8hi) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srai_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psradi256_mask ((__v8si) __A, __imm, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srai_epi32 (__mmask8 __U, __m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psradi256_mask ((__v8si) __A, __imm, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srai_epi32 (__m128i __W, __mmask8 __U, __m128i __A, + const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psradi128_mask ((__v4si) __A, __imm, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srai_epi32 (__mmask8 __U, __m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psradi128_mask ((__v4si) __A, __imm, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_srai_epi64 (__m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psraqi256_mask ((__v4di) __A, __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_srai_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psraqi256_mask ((__v4di) __A, __imm, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_srai_epi64 (__mmask8 __U, __m256i __A, const unsigned int __imm) +{ + return (__m256i) __builtin_ia32_psraqi256_mask ((__v4di) __A, __imm, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srai_epi64 (__m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psraqi128_mask ((__v2di) __A, __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_srai_epi64 (__m128i __W, __mmask8 __U, __m128i __A, + const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psraqi128_mask ((__v2di) __A, __imm, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_srai_epi64 (__mmask8 __U, __m128i __A, const unsigned int __imm) +{ + return (__m128i) __builtin_ia32_psraqi128_mask ((__v2di) __A, __imm, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_slli_epi32 (__m128i __W, __mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_pslldi128_mask ((__v4si) __A, __B, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_slli_epi32 (__mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_pslldi128_mask ((__v4si) __A, __B, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_slli_epi64 (__m128i __W, __mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_psllqi128_mask ((__v2di) __A, __B, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_slli_epi64 (__mmask8 __U, __m128i __A, unsigned int __B) +{ + return (__m128i) __builtin_ia32_psllqi128_mask ((__v2di) __A, __B, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_slli_epi32 (__m256i __W, __mmask8 __U, __m256i __A, + unsigned int __B) +{ + return (__m256i) __builtin_ia32_pslldi256_mask ((__v8si) __A, __B, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_slli_epi32 (__mmask8 __U, __m256i __A, unsigned int __B) +{ + return (__m256i) __builtin_ia32_pslldi256_mask ((__v8si) __A, __B, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_slli_epi64 (__m256i __W, __mmask8 __U, __m256i __A, + unsigned int __B) +{ + return (__m256i) __builtin_ia32_psllqi256_mask ((__v4di) __A, __B, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_slli_epi64 (__mmask8 __U, __m256i __A, unsigned int __B) +{ + return (__m256i) __builtin_ia32_psllqi256_mask ((__v4di) __A, __B, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permutex_pd (__m256d __W, __mmask8 __U, __m256d __X, + const int __imm) +{ + return (__m256d) __builtin_ia32_permdf256_mask ((__v4df) __X, __imm, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permutex_pd (__mmask8 __U, __m256d __X, const int __imm) +{ + return (__m256d) __builtin_ia32_permdf256_mask ((__v4df) __X, __imm, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permute_pd (__m256d __W, __mmask8 __U, __m256d __X, + const int __C) +{ + return (__m256d) __builtin_ia32_vpermilpd256_mask ((__v4df) __X, __C, + (__v4df) __W, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permute_pd (__mmask8 __U, __m256d __X, const int __C) +{ + return (__m256d) __builtin_ia32_vpermilpd256_mask ((__v4df) __X, __C, + (__v4df) + _mm256_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permute_pd (__m128d __W, __mmask8 __U, __m128d __X, + const int __C) +{ + return (__m128d) __builtin_ia32_vpermilpd_mask ((__v2df) __X, __C, + (__v2df) __W, + (__mmask8) __U); +} + +extern __inline __m128d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permute_pd (__mmask8 __U, __m128d __X, const int __C) +{ + return (__m128d) __builtin_ia32_vpermilpd_mask ((__v2df) __X, __C, + (__v2df) + _mm_avx512_setzero_pd (), + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_permute_ps (__m256 __W, __mmask8 __U, __m256 __X, + const int __C) +{ + return (__m256) __builtin_ia32_vpermilps256_mask ((__v8sf) __X, __C, + (__v8sf) __W, + (__mmask8) __U); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_permute_ps (__mmask8 __U, __m256 __X, const int __C) +{ + return (__m256) __builtin_ia32_vpermilps256_mask ((__v8sf) __X, __C, + (__v8sf) + _mm256_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_permute_ps (__m128 __W, __mmask8 __U, __m128 __X, + const int __C) +{ + return (__m128) __builtin_ia32_vpermilps_mask ((__v4sf) __X, __C, + (__v4sf) __W, + (__mmask8) __U); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_permute_ps (__mmask8 __U, __m128 __X, const int __C) +{ + return (__m128) __builtin_ia32_vpermilps_mask ((__v4sf) __X, __C, + (__v4sf) + _mm_avx512_setzero_ps (), + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epi64_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epi32_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epu64_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_epu32_mask (__m256i __X, __m256i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_pd_mask (__m256d __X, __m256d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd256_mask ((__v4df) __X, + (__v4df) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_ps_mask (__m256 __X, __m256 __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpps256_mask ((__v8sf) __X, + (__v8sf) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epi64_mask (__mmask8 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq256_mask ((__v4di) __X, + (__v4di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epi32_mask (__mmask8 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpd256_mask ((__v8si) __X, + (__v8si) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epu64_mask (__mmask8 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di) __X, + (__v4di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_epu32_mask (__mmask8 __U, __m256i __X, __m256i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si) __X, + (__v8si) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_pd_mask (__mmask8 __U, __m256d __X, __m256d __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd256_mask ((__v4df) __X, + (__v4df) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_cmp_ps_mask (__mmask8 __U, __m256 __X, __m256 __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpps256_mask ((__v8sf) __X, + (__v8sf) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epi64_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epi32_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epu64_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_epu32_mask (__m128i __X, __m128i __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_pd_mask (__m128d __X, __m128d __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd128_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ps_mask (__m128 __X, __m128 __Y, const int __P) +{ + return (__mmask8) __builtin_ia32_cmpps128_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) -1); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epi64_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpq128_mask ((__v2di) __X, + (__v2di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epi32_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpd128_mask ((__v4si) __X, + (__v4si) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epu64_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di) __X, + (__v2di) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_epu32_mask (__mmask8 __U, __m128i __X, __m128i __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si) __X, + (__v4si) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_pd_mask (__mmask8 __U, __m128d __X, __m128d __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmppd128_mask ((__v2df) __X, + (__v2df) __Y, __P, + (__mmask8) __U); +} + +extern __inline __mmask8 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_cmp_ps_mask (__mmask8 __U, __m128 __X, __m128 __Y, + const int __P) +{ + return (__mmask8) __builtin_ia32_cmpps128_mask ((__v4sf) __X, + (__v4sf) __Y, __P, + (__mmask8) __U); +} + +extern __inline __m256d +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutex_pd (__m256d __X, const int __M) +{ + return (__m256d) __builtin_ia32_permdf256_mask ((__v4df) __X, __M, + (__v4df) + _mm256_avx512_undefined_pd (), + (__mmask8) -1); +} + +#else +#define _mm256_permutex_pd(X, M) \ + ((__m256d) __builtin_ia32_permdf256_mask ((__v4df)(__m256d)(X), (int)(M), \ + (__v4df)(__m256d) \ + _mm256_avx512_undefined_pd (), \ + (__mmask8)-1)) + +#define _mm256_permutex_epi64(X, I) \ + ((__m256i) __builtin_ia32_permdi256_mask ((__v4di)(__m256i)(X), \ + (int)(I), \ + (__v4di)(__m256i) \ + (_mm256_avx512_setzero_si256 ()),\ + (__mmask8) -1)) + +#define _mm256_maskz_permutex_epi64(M, X, I) \ + ((__m256i) __builtin_ia32_permdi256_mask ((__v4di)(__m256i)(X), \ + (int)(I), \ + (__v4di)(__m256i) \ + (_mm256_avx512_setzero_si256 ()),\ + (__mmask8)(M))) + +#define _mm256_mask_permutex_epi64(W, M, X, I) \ + ((__m256i) __builtin_ia32_permdi256_mask ((__v4di)(__m256i)(X), \ + (int)(I), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(M))) + +#define _mm256_insertf32x4(X, Y, C) \ + ((__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf)(__m256) (X), \ + (__v4sf)(__m128) (Y), (int) (C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm256_mask_insertf32x4(W, U, X, Y, C) \ + ((__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf)(__m256) (X), \ + (__v4sf)(__m128) (Y), (int) (C), \ + (__v8sf)(__m256)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_insertf32x4(U, X, Y, C) \ + ((__m256) __builtin_ia32_insertf32x4_256_mask ((__v8sf)(__m256) (X), \ + (__v4sf)(__m128) (Y), (int) (C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_inserti32x4(X, Y, C) \ + ((__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si)(__m256i) (X),\ + (__v4si)(__m128i) (Y), (int) (C), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)-1)) + +#define _mm256_mask_inserti32x4(W, U, X, Y, C) \ + ((__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si)(__m256i) (X),\ + (__v4si)(__m128i) (Y), (int) (C), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_inserti32x4(U, X, Y, C) \ + ((__m256i) __builtin_ia32_inserti32x4_256_mask ((__v8si)(__m256i) (X),\ + (__v4si)(__m128i) (Y), (int) (C), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm256_extractf32x4_ps(X, C) \ + ((__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf)(__m256) (X), \ + (int) (C), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm256_mask_extractf32x4_ps(W, U, X, C) \ + ((__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf)(__m256) (X), \ + (int) (C), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_extractf32x4_ps(U, X, C) \ + ((__m128) __builtin_ia32_extractf32x4_256_mask ((__v8sf)(__m256) (X), \ + (int) (C), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_extracti32x4_epi32(X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si)(__m256i) (X),\ + (int) (C), (__v4si)(__m128i)_mm_avx512_setzero_si128 (), (__mmask8)-1)) + +#define _mm256_mask_extracti32x4_epi32(W, U, X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si)(__m256i) (X),\ + (int) (C), (__v4si)(__m128i)(W), (__mmask8)(U))) + +#define _mm256_maskz_extracti32x4_epi32(U, X, C) \ + ((__m128i) __builtin_ia32_extracti32x4_256_mask ((__v8si)(__m256i) (X),\ + (int) (C), (__v4si)(__m128i)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_shuffle_i64x2(X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)-1)) + +#define _mm256_mask_shuffle_i64x2(W, U, X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), \ + (__v4di)(__m256i)(W),\ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_i64x2(U, X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i64x2_256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm256_shuffle_i32x4(X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), \ + (__v8si)(__m256i) \ + _mm256_avx512_setzero_si256 (), \ + (__mmask8)-1)) + +#define _mm256_mask_shuffle_i32x4(W, U, X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_i32x4(U, X, Y, C) \ + ((__m256i) __builtin_ia32_shuf_i32x4_256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), \ + (__v8si)(__m256i) \ + _mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm256_shuffle_f64x2(X, Y, C) \ + ((__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(C), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd (),\ + (__mmask8)-1)) + +#define _mm256_mask_shuffle_f64x2(W, U, X, Y, C) \ + ((__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(C), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_f64x2(U, X, Y, C) \ + ((__m256d) __builtin_ia32_shuf_f64x2_256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(C), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd( ),\ + (__mmask8)(U))) + +#define _mm256_shuffle_f32x4(X, Y, C) \ + ((__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm256_mask_shuffle_f32x4(W, U, X, Y, C) \ + ((__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(C), \ + (__v8sf)(__m256)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_f32x4(U, X, Y, C) \ + ((__m256) __builtin_ia32_shuf_f32x4_256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_mask_shuffle_pd(W, U, A, B, C) \ + ((__m256d)__builtin_ia32_shufpd256_mask ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(C), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_pd(U, A, B, C) \ + ((__m256d)__builtin_ia32_shufpd256_mask ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(C), \ + (__v4df)(__m256d) \ + _mm256_avx512_setzero_pd (), \ + (__mmask8)(U))) + +#define _mm_mask_shuffle_pd(W, U, A, B, C) \ + ((__m128d)__builtin_ia32_shufpd128_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_shuffle_pd(U, A, B, C) \ + ((__m128d)__builtin_ia32_shufpd128_mask ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), \ + (__v2df)(__m128d)_mm_avx512_setzero_pd (), \ + (__mmask8)(U))) + +#define _mm256_mask_shuffle_ps(W, U, A, B, C) \ + ((__m256) __builtin_ia32_shufps256_mask ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(C), \ + (__v8sf)(__m256)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_ps(U, A, B, C) \ + ((__m256) __builtin_ia32_shufps256_mask ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (),\ + (__mmask8)(U))) + +#define _mm_mask_shuffle_ps(W, U, A, B, C) \ + ((__m128) __builtin_ia32_shufps128_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_shuffle_ps(U, A, B, C) \ + ((__m128) __builtin_ia32_shufps128_mask ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_fixupimm_pd(X, Y, Z, C) \ + ((__m256d)__builtin_ia32_fixupimmpd256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), \ + (__v4di)(__m256i)(Z), (int)(C), \ + (__mmask8)(-1))) + +#define _mm256_mask_fixupimm_pd(X, U, Y, Z, C) \ + ((__m256d)__builtin_ia32_fixupimmpd256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), \ + (__v4di)(__m256i)(Z), (int)(C), \ + (__mmask8)(U))) + +#define _mm256_maskz_fixupimm_pd(U, X, Y, Z, C) \ + ((__m256d)__builtin_ia32_fixupimmpd256_maskz ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), \ + (__v4di)(__m256i)(Z), (int)(C),\ + (__mmask8)(U))) + +#define _mm256_fixupimm_ps(X, Y, Z, C) \ + ((__m256)__builtin_ia32_fixupimmps256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), \ + (__v8si)(__m256i)(Z), (int)(C), \ + (__mmask8)(-1))) + + +#define _mm256_mask_fixupimm_ps(X, U, Y, Z, C) \ + ((__m256)__builtin_ia32_fixupimmps256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), \ + (__v8si)(__m256i)(Z), (int)(C), \ + (__mmask8)(U))) + +#define _mm256_maskz_fixupimm_ps(U, X, Y, Z, C) \ + ((__m256)__builtin_ia32_fixupimmps256_maskz ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), \ + (__v8si)(__m256i)(Z), (int)(C),\ + (__mmask8)(U))) + +#define _mm_fixupimm_pd(X, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmpd128_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1))) + + +#define _mm_mask_fixupimm_pd(X, U, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmpd128_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (__v2di)(__m128i)(Z), (int)(C), \ + (__mmask8)(U))) + +#define _mm_maskz_fixupimm_pd(U, X, Y, Z, C) \ + ((__m128d)__builtin_ia32_fixupimmpd128_maskz ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (__v2di)(__m128i)(Z), (int)(C),\ + (__mmask8)(U))) + +#define _mm_fixupimm_ps(X, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmps128_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (__v4si)(__m128i)(Z), (int)(C), \ + (__mmask8)(-1))) + +#define _mm_mask_fixupimm_ps(X, U, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmps128_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (__v4si)(__m128i)(Z), (int)(C),\ + (__mmask8)(U))) + +#define _mm_maskz_fixupimm_ps(U, X, Y, Z, C) \ + ((__m128)__builtin_ia32_fixupimmps128_maskz ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (__v4si)(__m128i)(Z), (int)(C),\ + (__mmask8)(U))) + +#define _mm256_mask_srli_epi32(W, U, A, B) \ + ((__m256i) __builtin_ia32_psrldi256_mask ((__v8si)(__m256i)(A), \ + (unsigned int)(B), (__v8si)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_srli_epi32(U, A, B) \ + ((__m256i) __builtin_ia32_psrldi256_mask ((__v8si)(__m256i)(A), \ + (unsigned int)(B), (__v8si)_mm256_avx512_setzero_si256 (), (__mmask8)(U))) + +#define _mm_mask_srli_epi32(W, U, A, B) \ + ((__m128i) __builtin_ia32_psrldi128_mask ((__v4si)(__m128i)(A), \ + (unsigned int)(B), (__v4si)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srli_epi32(U, A, B) \ + ((__m128i) __builtin_ia32_psrldi128_mask ((__v4si)(__m128i)(A), \ + (unsigned int)(B), (__v4si)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_mask_srli_epi64(W, U, A, B) \ + ((__m256i) __builtin_ia32_psrlqi256_mask ((__v4di)(__m256i)(A), \ + (unsigned int)(B), (__v4di)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_srli_epi64(U, A, B) \ + ((__m256i) __builtin_ia32_psrlqi256_mask ((__v4di)(__m256i)(A), \ + (unsigned int)(B), (__v4di)_mm256_avx512_setzero_si256 (), (__mmask8)(U))) + +#define _mm_mask_srli_epi64(W, U, A, B) \ + ((__m128i) __builtin_ia32_psrlqi128_mask ((__v2di)(__m128i)(A), \ + (unsigned int)(B), (__v2di)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srli_epi64(U, A, B) \ + ((__m128i) __builtin_ia32_psrlqi128_mask ((__v2di)(__m128i)(A), \ + (unsigned int)(B), (__v2di)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_mask_slli_epi32(W, U, X, C) \ + ((__m256i)__builtin_ia32_pslldi256_mask ((__v8si)(__m256i)(X), \ + (unsigned int)(C), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_slli_epi32(U, X, C) \ + ((__m256i)__builtin_ia32_pslldi256_mask ((__v8si)(__m256i)(X), \ + (unsigned int)(C), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm256_mask_slli_epi64(W, U, X, C) \ + ((__m256i)__builtin_ia32_psllqi256_mask ((__v4di)(__m256i)(X), \ + (unsigned int)(C), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_slli_epi64(U, X, C) \ + ((__m256i)__builtin_ia32_psllqi256_mask ((__v4di)(__m256i)(X), \ + (unsigned int)(C), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm_mask_slli_epi32(W, U, X, C) \ + ((__m128i)__builtin_ia32_pslldi128_mask ((__v4si)(__m128i)(X), \ + (unsigned int)(C), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_slli_epi32(U, X, C) \ + ((__m128i)__builtin_ia32_pslldi128_mask ((__v4si)(__m128i)(X), \ + (unsigned int)(C), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm_mask_slli_epi64(W, U, X, C) \ + ((__m128i)__builtin_ia32_psllqi128_mask ((__v2di)(__m128i)(X), \ + (unsigned int)(C), \ + (__v2di)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_slli_epi64(U, X, C) \ + ((__m128i)__builtin_ia32_psllqi128_mask ((__v2di)(__m128i)(X), \ + (unsigned int)(C), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm256_ternarylogic_epi64(A, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogq256_mask ((__v4di) (__m256i) (A), \ + (__v4di) (__m256i) (B), \ + (__v4di) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) -1)) + +#define _mm256_mask_ternarylogic_epi64(A, U, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogq256_mask ((__v4di) (__m256i) (A), \ + (__v4di) (__m256i) (B), \ + (__v4di) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm256_maskz_ternarylogic_epi64(U, A, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogq256_maskz ((__v4di) (__m256i) (A), \ + (__v4di) (__m256i) (B), \ + (__v4di) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm256_ternarylogic_epi32(A, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogd256_mask ((__v8si) (__m256i) (A), \ + (__v8si) (__m256i) (B), \ + (__v8si) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) -1)) + +#define _mm256_mask_ternarylogic_epi32(A, U, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogd256_mask ((__v8si) (__m256i) (A), \ + (__v8si) (__m256i) (B), \ + (__v8si) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm256_maskz_ternarylogic_epi32(U, A, B, C, I) \ + ((__m256i) \ + __builtin_ia32_pternlogd256_maskz ((__v8si) (__m256i) (A), \ + (__v8si) (__m256i) (B), \ + (__v8si) (__m256i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm_ternarylogic_epi64(A, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogq128_mask ((__v2di) (__m128i) (A), \ + (__v2di) (__m128i) (B), \ + (__v2di) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) -1)) + +#define _mm_mask_ternarylogic_epi64(A, U, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogq128_mask ((__v2di) (__m128i) (A), \ + (__v2di) (__m128i) (B), \ + (__v2di) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm_maskz_ternarylogic_epi64(U, A, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogq128_maskz ((__v2di) (__m128i) (A), \ + (__v2di) (__m128i) (B), \ + (__v2di) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm_ternarylogic_epi32(A, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogd128_mask ((__v4si) (__m128i) (A), \ + (__v4si) (__m128i) (B), \ + (__v4si) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) -1)) + +#define _mm_mask_ternarylogic_epi32(A, U, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogd128_mask ((__v4si) (__m128i) (A), \ + (__v4si) (__m128i) (B), \ + (__v4si) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm_maskz_ternarylogic_epi32(U, A, B, C, I) \ + ((__m128i) \ + __builtin_ia32_pternlogd128_maskz ((__v4si) (__m128i) (A), \ + (__v4si) (__m128i) (B), \ + (__v4si) (__m128i) (C), \ + (unsigned char) (I), \ + (__mmask8) (U))) + +#define _mm256_roundscale_ps(A, B) \ + ((__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)(__m256)_mm256_avx512_setzero_ps (), (__mmask8)-1)) + +#define _mm256_mask_roundscale_ps(W, U, A, B) \ + ((__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)(__m256)(W), (__mmask8)(U))) + +#define _mm256_maskz_roundscale_ps(U, A, B) \ + ((__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf)(__m256)(A), \ + (int)(B), (__v8sf)(__m256)_mm256_avx512_setzero_ps (), (__mmask8)(U))) + +#define _mm256_roundscale_pd(A, B) \ + ((__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)_mm256_avx512_setzero_pd (), (__mmask8)-1)) + +#define _mm256_mask_roundscale_pd(W, U, A, B) \ + ((__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)(W), (__mmask8)(U))) + +#define _mm256_maskz_roundscale_pd(U, A, B) \ + ((__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)_mm256_avx512_setzero_pd (), (__mmask8)(U))) + +#define _mm_roundscale_ps(A, B) \ + ((__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)(__m128)_mm_avx512_setzero_ps (), (__mmask8)-1)) + +#define _mm_mask_roundscale_ps(W, U, A, B) \ + ((__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)(__m128)(W), (__mmask8)(U))) + +#define _mm_maskz_roundscale_ps(U, A, B) \ + ((__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf)(__m128)(A), \ + (int)(B), (__v4sf)(__m128)_mm_avx512_setzero_ps (), (__mmask8)(U))) + +#define _mm_roundscale_pd(A, B) \ + ((__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)(__m128d)_mm_avx512_setzero_pd (), (__mmask8)-1)) + +#define _mm_mask_roundscale_pd(W, U, A, B) \ + ((__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)(__m128d)(W), (__mmask8)(U))) + +#define _mm_maskz_roundscale_pd(U, A, B) \ + ((__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df)(__m128d)(A), \ + (int)(B), (__v2df)(__m128d)_mm_avx512_setzero_pd (), (__mmask8)(U))) + +#define _mm256_getmant_ps(X, B, C) \ + ((__m256) __builtin_ia32_getmantps256_mask ((__v8sf)(__m256) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm256_mask_getmant_ps(W, U, X, B, C) \ + ((__m256) __builtin_ia32_getmantps256_mask ((__v8sf)(__m256) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8sf)(__m256)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_getmant_ps(U, X, B, C) \ + ((__m256) __builtin_ia32_getmantps256_mask ((__v8sf)(__m256) (X), \ + (int)(((C)<<2) | (B)), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm_getmant_ps(X, B, C) \ + ((__m128) __builtin_ia32_getmantps128_mask ((__v4sf)(__m128) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)-1)) + +#define _mm_mask_getmant_ps(W, U, X, B, C) \ + ((__m128) __builtin_ia32_getmantps128_mask ((__v4sf)(__m128) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_getmant_ps(U, X, B, C) \ + ((__m128) __builtin_ia32_getmantps128_mask ((__v4sf)(__m128) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_getmant_pd(X, B, C) \ + ((__m256d) __builtin_ia32_getmantpd256_mask ((__v4df)(__m256d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd (),\ + (__mmask8)-1)) + +#define _mm256_mask_getmant_pd(W, U, X, B, C) \ + ((__m256d) __builtin_ia32_getmantpd256_mask ((__v4df)(__m256d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_getmant_pd(U, X, B, C) \ + ((__m256d) __builtin_ia32_getmantpd256_mask ((__v4df)(__m256d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd (),\ + (__mmask8)(U))) + +#define _mm_getmant_pd(X, B, C) \ + ((__m128d) __builtin_ia32_getmantpd128_mask ((__v2df)(__m128d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v2df)(__m128d)_mm_avx512_setzero_pd (), \ + (__mmask8)-1)) + +#define _mm_mask_getmant_pd(W, U, X, B, C) \ + ((__m128d) __builtin_ia32_getmantpd128_mask ((__v2df)(__m128d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_getmant_pd(U, X, B, C) \ + ((__m128d) __builtin_ia32_getmantpd128_mask ((__v2df)(__m128d) (X), \ + (int)(((C)<<2) | (B)), \ + (__v2df)(__m128d)_mm_avx512_setzero_pd (), \ + (__mmask8)(U))) + +#define _mm256_mmask_i32gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256) __builtin_ia32_gather3siv8sf ((__v8sf)(__m256) (V1OLD), \ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i32gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128) __builtin_ia32_gather3siv4sf ((__v4sf)(__m128) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i32gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256d) __builtin_ia32_gather3siv4df ((__v4df)(__m256d) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i32gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128d) __builtin_ia32_gather3siv2df ((__v2df)(__m128d) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i64gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128) __builtin_ia32_gather3div8sf ((__v4sf)(__m128) (V1OLD), \ + (void const *) (ADDR), \ + (__v4di)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i64gather_ps(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128) __builtin_ia32_gather3div4sf ((__v4sf)(__m128) (V1OLD), \ + (void const *) (ADDR), \ + (__v2di)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i64gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256d) __builtin_ia32_gather3div4df ((__v4df)(__m256d) (V1OLD), \ + (void const *) (ADDR), \ + (__v4di)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i64gather_pd(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128d) __builtin_ia32_gather3div2df ((__v2df)(__m128d) (V1OLD), \ + (void const *) (ADDR), \ + (__v2di)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i32gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256i) __builtin_ia32_gather3siv8si ((__v8si)(__m256i) (V1OLD), \ + (void const *) (ADDR), \ + (__v8si)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i32gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128i) __builtin_ia32_gather3siv4si ((__v4si)(__m128i) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i32gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256i) __builtin_ia32_gather3siv4di ((__v4di)(__m256i) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i32gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128i) __builtin_ia32_gather3siv2di ((__v2di)(__m128i) (V1OLD), \ + (void const *) (ADDR), \ + (__v4si)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i64gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128i) __builtin_ia32_gather3div8si ((__v4si)(__m128i) (V1OLD), \ + (void const *) (ADDR), \ + (__v4di)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i64gather_epi32(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128i) __builtin_ia32_gather3div4si ((__v4si)(__m128i) (V1OLD), \ + (void const *) (ADDR), \ + (__v2di)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_mmask_i64gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m256i) __builtin_ia32_gather3div4di ((__v4di)(__m256i) (V1OLD), \ + (void const *) (ADDR), \ + (__v4di)(__m256i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm_mmask_i64gather_epi64(V1OLD, MASK, INDEX, ADDR, SCALE) \ + (__m128i) __builtin_ia32_gather3div2di ((__v2di)(__m128i) (V1OLD), \ + (void const *) (ADDR), \ + (__v2di)(__m128i) (INDEX), \ + (__mmask8) (MASK), \ + (int) (SCALE)) + +#define _mm256_i32scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8sf ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8si)(__m256i) (INDEX), \ + (__v8sf)(__m256) (V1), (int) (SCALE)) + +#define _mm256_mask_i32scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8sf ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8si)(__m256i) (INDEX), \ + (__v8sf)(__m256) (V1), (int) (SCALE)) + +#define _mm_i32scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4sf ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm_mask_i32scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4sf ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm256_i32scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v4df)(__m256d) (V1), (int) (SCALE)) + +#define _mm256_mask_i32scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v4df)(__m256d) (V1), (int) (SCALE)) + +#define _mm_i32scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv2df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v2df)(__m128d) (V1), (int) (SCALE)) + +#define _mm_mask_i32scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv2df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v2df)(__m128d) (V1), (int) (SCALE)) + +#define _mm256_i64scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8sf ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4di)(__m256i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm256_mask_i64scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8sf ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4di)(__m256i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm_i64scatter_ps(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4sf ((void *) (ADDR), (__mmask8)0xFF, \ + (__v2di)(__m128i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm_mask_i64scatter_ps(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4sf ((void *) (ADDR), (__mmask8) (MASK), \ + (__v2di)(__m128i) (INDEX), \ + (__v4sf)(__m128) (V1), (int) (SCALE)) + +#define _mm256_i64scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4di)(__m256i) (INDEX), \ + (__v4df)(__m256d) (V1), (int) (SCALE)) + +#define _mm256_mask_i64scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4di)(__m256i) (INDEX), \ + (__v4df)(__m256d) (V1), (int) (SCALE)) + +#define _mm_i64scatter_pd(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv2df ((void *) (ADDR), (__mmask8)0xFF, \ + (__v2di)(__m128i) (INDEX), \ + (__v2df)(__m128d) (V1), (int) (SCALE)) + +#define _mm_mask_i64scatter_pd(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv2df ((void *) (ADDR), (__mmask8) (MASK), \ + (__v2di)(__m128i) (INDEX), \ + (__v2df)(__m128d) (V1), (int) (SCALE)) + +#define _mm256_i32scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8si ((void *) (ADDR), (__mmask8)0xFF, \ + (__v8si)(__m256i) (INDEX), \ + (__v8si)(__m256i) (V1), (int) (SCALE)) + +#define _mm256_mask_i32scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv8si ((void *) (ADDR), (__mmask8) (MASK), \ + (__v8si)(__m256i) (INDEX), \ + (__v8si)(__m256i) (V1), (int) (SCALE)) + +#define _mm_i32scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4si ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm_mask_i32scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4si ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm256_i32scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v4di)(__m256i) (V1), (int) (SCALE)) + +#define _mm256_mask_i32scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv4di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v4di)(__m256i) (V1), (int) (SCALE)) + +#define _mm_i32scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv2di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4si)(__m128i) (INDEX), \ + (__v2di)(__m128i) (V1), (int) (SCALE)) + +#define _mm_mask_i32scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scattersiv2di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4si)(__m128i) (INDEX), \ + (__v2di)(__m128i) (V1), (int) (SCALE)) + +#define _mm256_i64scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8si ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4di)(__m256i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm256_mask_i64scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv8si ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4di)(__m256i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm_i64scatter_epi32(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4si ((void *) (ADDR), (__mmask8)0xFF, \ + (__v2di)(__m128i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm_mask_i64scatter_epi32(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4si ((void *) (ADDR), (__mmask8) (MASK), \ + (__v2di)(__m128i) (INDEX), \ + (__v4si)(__m128i) (V1), (int) (SCALE)) + +#define _mm256_i64scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v4di)(__m256i) (INDEX), \ + (__v4di)(__m256i) (V1), (int) (SCALE)) + +#define _mm256_mask_i64scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv4di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v4di)(__m256i) (INDEX), \ + (__v4di)(__m256i) (V1), (int) (SCALE)) + +#define _mm_i64scatter_epi64(ADDR, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv2di ((void *) (ADDR), (__mmask8)0xFF, \ + (__v2di)(__m128i) (INDEX), \ + (__v2di)(__m128i) (V1), (int) (SCALE)) + +#define _mm_mask_i64scatter_epi64(ADDR, MASK, INDEX, V1, SCALE) \ + __builtin_ia32_scatterdiv2di ((void *) (ADDR), (__mmask8) (MASK), \ + (__v2di)(__m128i) (INDEX), \ + (__v2di)(__m128i) (V1), (int) (SCALE)) + +#define _mm256_mask_shuffle_epi32(W, U, X, C) \ + ((__m256i) __builtin_ia32_pshufd256_mask ((__v8si)(__m256i)(X), (int)(C), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_shuffle_epi32(U, X, C) \ + ((__m256i) __builtin_ia32_pshufd256_mask ((__v8si)(__m256i)(X), (int)(C), \ + (__v8si)(__m256i) \ + _mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm_mask_shuffle_epi32(W, U, X, C) \ + ((__m128i) __builtin_ia32_pshufd128_mask ((__v4si)(__m128i)(X), (int)(C), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_shuffle_epi32(U, X, C) \ + ((__m128i) __builtin_ia32_pshufd128_mask ((__v4si)(__m128i)(X), (int)(C), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (), \ + (__mmask8)(U))) + +#define _mm256_rol_epi64(A, B) \ + ((__m256i)__builtin_ia32_prolq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)-1)) + +#define _mm256_mask_rol_epi64(W, U, A, B) \ + ((__m256i)__builtin_ia32_prolq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_rol_epi64(U, A, B) \ + ((__m256i)__builtin_ia32_prolq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm_rol_epi64(A, B) \ + ((__m128i)__builtin_ia32_prolq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)-1)) + +#define _mm_mask_rol_epi64(W, U, A, B) \ + ((__m128i)__builtin_ia32_prolq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_rol_epi64(U, A, B) \ + ((__m128i)__builtin_ia32_prolq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm256_ror_epi64(A, B) \ + ((__m256i)__builtin_ia32_prorq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)-1)) + +#define _mm256_mask_ror_epi64(W, U, A, B) \ + ((__m256i)__builtin_ia32_prorq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_ror_epi64(U, A, B) \ + ((__m256i)__builtin_ia32_prorq256_mask ((__v4di)(__m256i)(A), (int)(B), \ + (__v4di)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm_ror_epi64(A, B) \ + ((__m128i)__builtin_ia32_prorq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)-1)) + +#define _mm_mask_ror_epi64(W, U, A, B) \ + ((__m128i)__builtin_ia32_prorq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_ror_epi64(U, A, B) \ + ((__m128i)__builtin_ia32_prorq128_mask ((__v2di)(__m128i)(A), (int)(B), \ + (__v2di)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm256_rol_epi32(A, B) \ + ((__m256i)__builtin_ia32_prold256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)-1)) + +#define _mm256_mask_rol_epi32(W, U, A, B) \ + ((__m256i)__builtin_ia32_prold256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_rol_epi32(U, A, B) \ + ((__m256i)__builtin_ia32_prold256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm_rol_epi32(A, B) \ + ((__m128i)__builtin_ia32_prold128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)-1)) + +#define _mm_mask_rol_epi32(W, U, A, B) \ + ((__m128i)__builtin_ia32_prold128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_rol_epi32(U, A, B) \ + ((__m128i)__builtin_ia32_prold128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm256_ror_epi32(A, B) \ + ((__m256i)__builtin_ia32_prord256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)-1)) + +#define _mm256_mask_ror_epi32(W, U, A, B) \ + ((__m256i)__builtin_ia32_prord256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_ror_epi32(U, A, B) \ + ((__m256i)__builtin_ia32_prord256_mask ((__v8si)(__m256i)(A), (int)(B), \ + (__v8si)(__m256i) \ + _mm256_avx512_setzero_si256 (), \ + (__mmask8)(U))) + +#define _mm_ror_epi32(A, B) \ + ((__m128i)__builtin_ia32_prord128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)-1)) + +#define _mm_mask_ror_epi32(W, U, A, B) \ + ((__m128i)__builtin_ia32_prord128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U))) + +#define _mm_maskz_ror_epi32(U, A, B) \ + ((__m128i)__builtin_ia32_prord128_mask ((__v4si)(__m128i)(A), (int)(B), \ + (__v4si)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm256_alignr_epi32(X, Y, C) \ + ((__m256i)__builtin_ia32_alignd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), (__v8si)(__m256i)(X), (__mmask8)-1)) + +#define _mm256_mask_alignr_epi32(W, U, X, Y, C) \ + ((__m256i)__builtin_ia32_alignd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), (__v8si)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_alignr_epi32(U, X, Y, C) \ + ((__m256i)__builtin_ia32_alignd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(C), (__v8si)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm256_alignr_epi64(X, Y, C) \ + ((__m256i)__builtin_ia32_alignq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), (__v4di)(__m256i)(X), (__mmask8)-1)) + +#define _mm256_mask_alignr_epi64(W, U, X, Y, C) \ + ((__m256i)__builtin_ia32_alignq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), (__v4di)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_alignr_epi64(U, X, Y, C) \ + ((__m256i)__builtin_ia32_alignq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(C), (__v4di)(__m256i)_mm256_avx512_setzero_si256 (),\ + (__mmask8)(U))) + +#define _mm_alignr_epi32(X, Y, C) \ + ((__m128i)__builtin_ia32_alignd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(C), (__v4si)(__m128i)(X), (__mmask8)-1)) + +#define _mm_mask_alignr_epi32(W, U, X, Y, C) \ + ((__m128i)__builtin_ia32_alignd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(C), (__v4si)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_alignr_epi32(U, X, Y, C) \ + ((__m128i)__builtin_ia32_alignd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(C), (__v4si)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm_alignr_epi64(X, Y, C) \ + ((__m128i)__builtin_ia32_alignq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(C), (__v2di)(__m128i)(X), (__mmask8)-1)) + +#define _mm_mask_alignr_epi64(W, U, X, Y, C) \ + ((__m128i)__builtin_ia32_alignq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(C), (__v2di)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_alignr_epi64(U, X, Y, C) \ + ((__m128i)__builtin_ia32_alignq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(C), (__v2di)(__m128i)_mm_avx512_setzero_si128 (),\ + (__mmask8)(U))) + +#define _mm_mask_cvtps_ph(W, U, A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf)(__m128) (A), (int) (I), \ + (__v8hi)(__m128i) (W), (__mmask8) (U))) + +#define _mm_maskz_cvtps_ph(U, A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf)(__m128) (A), (int) (I), \ + (__v8hi)(__m128i) _mm_avx512_setzero_si128 (), (__mmask8) (U))) + +#define _mm256_mask_cvtps_ph(W, U, A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf)(__m256) (A), (int) (I), \ + (__v8hi)(__m128i) (W), (__mmask8) (U))) + +#define _mm256_maskz_cvtps_ph(U, A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf)(__m256) (A), (int) (I), \ + (__v8hi)(__m128i) _mm_avx512_setzero_si128 (), (__mmask8) (U))) + +#define _mm256_mask_srai_epi32(W, U, A, B) \ + ((__m256i) __builtin_ia32_psradi256_mask ((__v8si)(__m256i)(A), \ + (unsigned int)(B), (__v8si)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_srai_epi32(U, A, B) \ + ((__m256i) __builtin_ia32_psradi256_mask ((__v8si)(__m256i)(A), \ + (unsigned int)(B), (__v8si)_mm256_avx512_setzero_si256 (), (__mmask8)(U))) + +#define _mm_mask_srai_epi32(W, U, A, B) \ + ((__m128i) __builtin_ia32_psradi128_mask ((__v4si)(__m128i)(A), \ + (unsigned int)(B), (__v4si)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srai_epi32(U, A, B) \ + ((__m128i) __builtin_ia32_psradi128_mask ((__v4si)(__m128i)(A), \ + (unsigned int)(B), (__v4si)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_srai_epi64(A, B) \ + ((__m256i) __builtin_ia32_psraqi256_mask ((__v4di)(__m256i)(A), \ + (unsigned int)(B), (__v4di)_mm256_avx512_setzero_si256 (), (__mmask8)-1)) + +#define _mm256_mask_srai_epi64(W, U, A, B) \ + ((__m256i) __builtin_ia32_psraqi256_mask ((__v4di)(__m256i)(A), \ + (unsigned int)(B), (__v4di)(__m256i)(W), (__mmask8)(U))) + +#define _mm256_maskz_srai_epi64(U, A, B) \ + ((__m256i) __builtin_ia32_psraqi256_mask ((__v4di)(__m256i)(A), \ + (unsigned int)(B), (__v4di)_mm256_avx512_setzero_si256 (), (__mmask8)(U))) + +#define _mm_srai_epi64(A, B) \ + ((__m128i) __builtin_ia32_psraqi128_mask ((__v2di)(__m128i)(A), \ + (unsigned int)(B), (__v2di)_mm_avx512_setzero_si128 (), (__mmask8)-1)) + +#define _mm_mask_srai_epi64(W, U, A, B) \ + ((__m128i) __builtin_ia32_psraqi128_mask ((__v2di)(__m128i)(A), \ + (unsigned int)(B), (__v2di)(__m128i)(W), (__mmask8)(U))) + +#define _mm_maskz_srai_epi64(U, A, B) \ + ((__m128i) __builtin_ia32_psraqi128_mask ((__v2di)(__m128i)(A), \ + (unsigned int)(B), (__v2di)_mm_avx512_setzero_si128 (), (__mmask8)(U))) + +#define _mm256_mask_permutex_pd(W, U, A, B) \ + ((__m256d) __builtin_ia32_permdf256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)(W), (__mmask8)(U))) + +#define _mm256_maskz_permutex_pd(U, A, B) \ + ((__m256d) __builtin_ia32_permdf256_mask ((__v4df)(__m256d)(A), \ + (int)(B), (__v4df)(__m256d)_mm256_avx512_setzero_pd (), (__mmask8)(U))) + +#define _mm256_mask_permute_pd(W, U, X, C) \ + ((__m256d) __builtin_ia32_vpermilpd256_mask ((__v4df)(__m256d)(X), (int)(C), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U))) + +#define _mm256_maskz_permute_pd(U, X, C) \ + ((__m256d) __builtin_ia32_vpermilpd256_mask ((__v4df)(__m256d)(X), (int)(C), \ + (__v4df)(__m256d)_mm256_avx512_setzero_pd (),\ + (__mmask8)(U))) + +#define _mm256_mask_permute_ps(W, U, X, C) \ + ((__m256) __builtin_ia32_vpermilps256_mask ((__v8sf)(__m256)(X), (int)(C), \ + (__v8sf)(__m256)(W), (__mmask8)(U))) + +#define _mm256_maskz_permute_ps(U, X, C) \ + ((__m256) __builtin_ia32_vpermilps256_mask ((__v8sf)(__m256)(X), (int)(C), \ + (__v8sf)(__m256)_mm256_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm_mask_permute_pd(W, U, X, C) \ + ((__m128d) __builtin_ia32_vpermilpd_mask ((__v2df)(__m128d)(X), (int)(C), \ + (__v2df)(__m128d)(W), (__mmask8)(U))) + +#define _mm_maskz_permute_pd(U, X, C) \ + ((__m128d) __builtin_ia32_vpermilpd_mask ((__v2df)(__m128d)(X), (int)(C), \ + (__v2df)(__m128d)_mm_avx512_setzero_pd (), \ + (__mmask8)(U))) + +#define _mm_mask_permute_ps(W, U, X, C) \ + ((__m128) __builtin_ia32_vpermilps_mask ((__v4sf)(__m128)(X), (int)(C), \ + (__v4sf)(__m128)(W), (__mmask8)(U))) + +#define _mm_maskz_permute_ps(U, X, C) \ + ((__m128) __builtin_ia32_vpermilps_mask ((__v4sf)(__m128)(X), (int)(C), \ + (__v4sf)(__m128)_mm_avx512_setzero_ps (), \ + (__mmask8)(U))) + +#define _mm256_cmp_epu32_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_cmp_epi64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_cmp_epi32_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_cmp_epu64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_cmp_pd_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_cmp_ps_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpps256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm256_mask_cmp_epi64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm256_mask_cmp_epi32_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm256_mask_cmp_epu64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq256_mask ((__v4di)(__m256i)(X), \ + (__v4di)(__m256i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm256_mask_cmp_epu32_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpd256_mask ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm256_mask_cmp_pd_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd256_mask ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm256_mask_cmp_ps_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpps256_mask ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_cmp_epi64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_cmp_epi32_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_cmp_epu64_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_cmp_epu32_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_cmp_pd_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd128_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_cmp_ps_mask(X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpps128_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P),\ + (__mmask8)-1)) + +#define _mm_mask_cmp_epi64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_epi32_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_epu64_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpq128_mask ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_epu32_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_ucmpd128_mask ((__v4si)(__m128i)(X), \ + (__v4si)(__m128i)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_pd_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmppd128_mask ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P),\ + (__mmask8)(M))) + +#define _mm_mask_cmp_ps_mask(M, X, Y, P) \ + ((__mmask8) __builtin_ia32_cmpps128_mask ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P),\ + (__mmask8)(M))) + +#endif + +#define _mm256_permutexvar_ps(A, B) _mm256_permutevar8x32_ps ((B), (A)) +#define _mm256_mask_cvt_roundps_ph(A, B, C, D) \ + _mm256_mask_cvtps_ph ((A), (B), (C), (D)) +#define _mm256_maskz_cvt_roundps_ph(A, B, C) \ + _mm256_maskz_cvtps_ph ((A), (B), (C)) +#define _mm_mask_cvt_roundps_ph(A, B, C, D) \ + _mm_mask_cvtps_ph ((A), (B), (C), (D)) +#define _mm_maskz_cvt_roundps_ph(A, B, C) _mm_maskz_cvtps_ph ((A), (B), (C)) + +#ifdef __DISABLE_AVX512VL__ +#undef __DISABLE_AVX512VL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VL__ */ + +#if !defined (__AVX512CD__) || !defined (__AVX512VL__) +#pragma GCC push_options +#pragma GCC target("avx512vl,avx512cd,no-evex512") +#define __DISABLE_AVX512VLCD__ +#endif + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastmb_epi64 (__mmask8 __A) +{ + return (__m128i) __builtin_ia32_broadcastmb128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastmb_epi64 (__mmask8 __A) +{ + return (__m256i) __builtin_ia32_broadcastmb256 (__A); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcastmw_epi32 (__mmask16 __A) +{ + return (__m128i) __builtin_ia32_broadcastmw128 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcastmw_epi32 (__mmask16 __A) +{ + return (__m256i) __builtin_ia32_broadcastmw256 (__A); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_lzcnt_epi32 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_lzcnt_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_lzcnt_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntd_256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_lzcnt_epi64 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_lzcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_lzcnt_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vplzcntq_256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_conflict_epi64 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_conflict_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_conflict_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_conflict_epi32 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) -1); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_conflict_epi32 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, + (__v8si) __W, + (__mmask8) + __U); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_conflict_epi32 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_lzcnt_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_lzcnt_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_lzcnt_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntd_128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_lzcnt_epi64 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_lzcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_lzcnt_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vplzcntq_128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_conflict_epi64 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_conflict_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_conflict_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_conflict_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) -1); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_conflict_epi32 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, + (__v4si) __W, + (__mmask8) + __U); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_conflict_epi32 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask8) + __U); +} + +#ifdef __DISABLE_AVX512VLCD__ +#pragma GCC pop_options +#endif + +#endif /* _AVX512VLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vnniintrin.h b/template/sysroot/include/avx512vnniintrin.h new file mode 100644 index 0000000..168e9aa --- /dev/null +++ b/template/sysroot/include/avx512vnniintrin.h @@ -0,0 +1,144 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef __AVX512VNNIINTRIN_H_INCLUDED +#define __AVX512VNNIINTRIN_H_INCLUDED + +#if !defined(__AVX512VNNI__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vnni,evex512") +#define __DISABLE_AVX512VNNI__ +#endif /* __AVX512VNNI__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dpbusd_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpdpbusd_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dpbusd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpbusd_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dpbusd_epi32 (__mmask16 __A, __m512i __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpbusd_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dpbusds_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpdpbusds_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dpbusds_epi32 (__m512i __A, __mmask16 __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpbusds_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dpbusds_epi32 (__mmask16 __A, __m512i __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpbusds_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpdpwssd_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dpwssd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpwssd_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dpwssd_epi32 (__mmask16 __A, __m512i __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpwssd_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vpdpwssds_v16si ((__v16si)__A, (__v16si) __B, + (__v16si) __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_dpwssds_epi32 (__m512i __A, __mmask16 __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpwssds_v16si_mask ((__v16si)__A, + (__v16si) __C, (__v16si) __D, (__mmask16)__B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_dpwssds_epi32 (__mmask16 __A, __m512i __B, __m512i __C, + __m512i __D) +{ + return (__m512i)__builtin_ia32_vpdpwssds_v16si_maskz ((__v16si)__B, + (__v16si) __C, (__v16si) __D, (__mmask16)__A); +} + +#ifdef __DISABLE_AVX512VNNI__ +#undef __DISABLE_AVX512VNNI__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VNNI__ */ + +#endif /* __AVX512VNNIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vnnivlintrin.h b/template/sysroot/include/avx512vnnivlintrin.h new file mode 100644 index 0000000..88d7dfc --- /dev/null +++ b/template/sysroot/include/avx512vnnivlintrin.h @@ -0,0 +1,210 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VNNIVLINTRIN_H_INCLUDED +#define _AVX512VNNIVLINTRIN_H_INCLUDED + +#if !defined(__AVX512VL__) || !defined(__AVX512VNNI__) || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vnni,avx512vl,no-evex512") +#define __DISABLE_AVX512VNNIVL__ +#endif /* __AVX512VNNIVL__ */ + +#define _mm256_dpbusd_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) (A), \ + (__v8si) (B), \ + (__v8si) (C))) + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dpbusd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpbusd_v8si_mask ((__v8si)__A, (__v8si) __C, + (__v8si) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dpbusd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpbusd_v8si_maskz ((__v8si)__B, + (__v8si) __C, (__v8si) __D, (__mmask8)__A); +} + +#define _mm_dpbusd_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) (A), \ + (__v4si) (B), \ + (__v4si) (C))) + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dpbusd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpbusd_v4si_mask ((__v4si)__A, (__v4si) __C, + (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dpbusd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpbusd_v4si_maskz ((__v4si)__B, + (__v4si) __C, (__v4si) __D, (__mmask8)__A); +} + +#define _mm256_dpbusds_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) (A), \ + (__v8si) (B), \ + (__v8si) (C))) + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dpbusds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpbusds_v8si_mask ((__v8si)__A, + (__v8si) __C, (__v8si) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dpbusds_epi32 (__mmask8 __A, __m256i __B, __m256i __C, + __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpbusds_v8si_maskz ((__v8si)__B, + (__v8si) __C, (__v8si) __D, (__mmask8)__A); +} + +#define _mm_dpbusds_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) (A), \ + (__v4si) (B), \ + (__v4si) (C))) + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dpbusds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpbusds_v4si_mask ((__v4si)__A, + (__v4si) __C, (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dpbusds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpbusds_v4si_maskz ((__v4si)__B, + (__v4si) __C, (__v4si) __D, (__mmask8)__A); +} + +#define _mm256_dpwssd_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) (A), \ + (__v8si) (B), \ + (__v8si) (C))) + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dpwssd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpwssd_v8si_mask ((__v8si)__A, (__v8si) __C, + (__v8si) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dpwssd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpwssd_v8si_maskz ((__v8si)__B, + (__v8si) __C, (__v8si) __D, (__mmask8)__A); +} + +#define _mm_dpwssd_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) (A), \ + (__v4si) (B), \ + (__v4si) (C))) + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dpwssd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpwssd_v4si_mask ((__v4si)__A, (__v4si) __C, + (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dpwssd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpwssd_v4si_maskz ((__v4si)__B, + (__v4si) __C, (__v4si) __D, (__mmask8)__A); +} + +#define _mm256_dpwssds_epi32(A, B, C) \ + ((__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) (A), \ + (__v8si) (B), \ + (__v8si) (C))) + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_dpwssds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpwssds_v8si_mask ((__v8si)__A, + (__v8si) __C, (__v8si) __D, (__mmask8)__B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_dpwssds_epi32 (__mmask8 __A, __m256i __B, __m256i __C, + __m256i __D) +{ + return (__m256i)__builtin_ia32_vpdpwssds_v8si_maskz ((__v8si)__B, + (__v8si) __C, (__v8si) __D, (__mmask8)__A); +} + +#define _mm_dpwssds_epi32(A, B, C) \ + ((__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) (A), \ + (__v4si) (B), \ + (__v4si) (C))) + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_dpwssds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpwssds_v4si_mask ((__v4si)__A, + (__v4si) __C, (__v4si) __D, (__mmask8)__B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_dpwssds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D) +{ + return (__m128i)__builtin_ia32_vpdpwssds_v4si_maskz ((__v4si)__B, + (__v4si) __C, (__v4si) __D, (__mmask8)__A); +} +#ifdef __DISABLE_AVX512VNNIVL__ +#undef __DISABLE_AVX512VNNIVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VNNIVL__ */ +#endif /* __DISABLE_AVX512VNNIVL__ */ diff --git a/template/sysroot/include/avx512vp2intersectintrin.h b/template/sysroot/include/avx512vp2intersectintrin.h new file mode 100644 index 0000000..5061b20 --- /dev/null +++ b/template/sysroot/include/avx512vp2intersectintrin.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VP2INTERSECTINTRIN_H_INCLUDED +#define _AVX512VP2INTERSECTINTRIN_H_INCLUDED + +#if !defined(__AVX512VP2INTERSECT__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vp2intersect,evex512") +#define __DISABLE_AVX512VP2INTERSECT__ +#endif /* __AVX512VP2INTERSECT__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_2intersect_epi32 (__m512i __A, __m512i __B, __mmask16 *__U, + __mmask16 *__M) +{ + __builtin_ia32_2intersectd512 (__U, __M, (__v16si) __A, (__v16si) __B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_2intersect_epi64 (__m512i __A, __m512i __B, __mmask8 *__U, + __mmask8 *__M) +{ + __builtin_ia32_2intersectq512 (__U, __M, (__v8di) __A, (__v8di) __B); +} + +#ifdef __DISABLE_AVX512VP2INTERSECT__ +#undef __DISABLE_AVX512VP2INTERSECT__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VP2INTERSECT__ */ + +#endif /* _AVX512VP2INTERSECTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vp2intersectvlintrin.h b/template/sysroot/include/avx512vp2intersectvlintrin.h new file mode 100644 index 0000000..546ccd9 --- /dev/null +++ b/template/sysroot/include/avx512vp2intersectvlintrin.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED +#define _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED + +#if !defined(__AVX512VP2INTERSECT__) || !defined(__AVX512VL__) \ + || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vp2intersect,avx512vl,no-evex512") +#define __DISABLE_AVX512VP2INTERSECTVL__ +#endif /* __AVX512VP2INTERSECTVL__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_2intersect_epi32 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M) +{ + __builtin_ia32_2intersectd128 (__U, __M, (__v4si) __A, (__v4si) __B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_2intersect_epi32 (__m256i __A, __m256i __B, __mmask8 *__U, + __mmask8 *__M) +{ + __builtin_ia32_2intersectd256 (__U, __M, (__v8si) __A, (__v8si) __B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_2intersect_epi64 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M) +{ + __builtin_ia32_2intersectq128 (__U, __M, (__v2di) __A, (__v2di) __B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_2intersect_epi64 (__m256i __A, __m256i __B, __mmask8 *__U, + __mmask8 *__M) +{ + __builtin_ia32_2intersectq256 (__U, __M, (__v4di) __A, (__v4di) __B); +} + +#ifdef __DISABLE_AVX512VP2INTERSECTVL__ +#undef __DISABLE_AVX512VP2INTERSECTVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VP2INTERSECTVL__ */ + +#endif /* _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vpopcntdqintrin.h b/template/sysroot/include/avx512vpopcntdqintrin.h new file mode 100644 index 0000000..e1fb322 --- /dev/null +++ b/template/sysroot/include/avx512vpopcntdqintrin.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX512VPOPCNTDQINTRIN_H_INCLUDED +#define _AVX512VPOPCNTDQINTRIN_H_INCLUDED + +#if !defined (__AVX512VPOPCNTDQ__) || !defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vpopcntdq,evex512") +#define __DISABLE_AVX512VPOPCNTDQ__ +#endif /* __AVX512VPOPCNTDQ__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_popcnt_epi32 (__m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountd_v16si ((__v16si) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_popcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A, + (__v16si) __W, + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_popcnt_epi32 (__mmask16 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A, + (__v16si) + _mm512_setzero_si512 (), + (__mmask16) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_popcnt_epi64 (__m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountq_v8di ((__v8di) __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_popcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A, + (__v8di) __W, + (__mmask8) __U); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_popcnt_epi64 (__mmask8 __U, __m512i __A) +{ + return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A, + (__v8di) + _mm512_setzero_si512 (), + (__mmask8) __U); +} + +#ifdef __DISABLE_AVX512VPOPCNTDQ__ +#undef __DISABLE_AVX512VPOPCNTDQ__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VPOPCNTDQ__ */ + +#endif /* _AVX512VPOPCNTDQINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avx512vpopcntdqvlintrin.h b/template/sysroot/include/avx512vpopcntdqvlintrin.h new file mode 100644 index 0000000..5352355 --- /dev/null +++ b/template/sysroot/include/avx512vpopcntdqvlintrin.h @@ -0,0 +1,147 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED +#define _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED + +#if !defined(__AVX512VPOPCNTDQ__) || !defined(__AVX512VL__) \ + || defined (__EVEX512__) +#pragma GCC push_options +#pragma GCC target("avx512vpopcntdq,avx512vl,no-evex512") +#define __DISABLE_AVX512VPOPCNTDQVL__ +#endif /* __AVX512VPOPCNTDQVL__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_epi32 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountd_v4si ((__v4si) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_popcnt_epi32 (__m128i __W, __mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A, + (__v4si) __W, + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_popcnt_epi32 (__mmask16 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A, + (__v4si) + _mm_avx512_setzero_si128 (), + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_popcnt_epi32 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountd_v8si ((__v8si) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_popcnt_epi32 (__m256i __W, __mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A, + (__v8si) __W, + (__mmask16) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_popcnt_epi32 (__mmask16 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A, + (__v8si) + _mm256_avx512_setzero_si256 (), + (__mmask16) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_epi64 (__m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountq_v2di ((__v2di) __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_popcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A, + (__v2di) __W, + (__mmask8) __U); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_popcnt_epi64 (__mmask8 __U, __m128i __A) +{ + return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A, + (__v2di) + _mm_avx512_setzero_si128 (), + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_popcnt_epi64 (__m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountq_v4di ((__v4di) __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_popcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A, + (__v4di) __W, + (__mmask8) __U); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_popcnt_epi64 (__mmask8 __U, __m256i __A) +{ + return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A, + (__v4di) + _mm256_avx512_setzero_si256 (), + (__mmask8) __U); +} + +#ifdef __DISABLE_AVX512VPOPCNTDQVL__ +#undef __DISABLE_AVX512VPOPCNTDQVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX512VPOPCNTDQVL__ */ + +#endif /* _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxifmaintrin.h b/template/sysroot/include/avxifmaintrin.h new file mode 100644 index 0000000..7438630 --- /dev/null +++ b/template/sysroot/include/avxifmaintrin.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXIFMAINTRIN_H_INCLUDED +#define _AVXIFMAINTRIN_H_INCLUDED + +#ifndef __AVXIFMA__ +#pragma GCC push_options +#pragma GCC target("avxifma") +#define __DISABLE_AVXIFMA__ +#endif /* __AVXIFMA__ */ + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_madd52lo_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z) +{ + return (__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) __X, + (__v2di) __Y, + (__v2di) __Z); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_madd52hi_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z) +{ + return (__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) __X, + (__v2di) __Y, + (__v2di) __Z); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_madd52lo_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z) +{ + return (__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) __X, + (__v4di) __Y, + (__v4di) __Z); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_madd52hi_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z) +{ + return (__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) __X, + (__v4di) __Y, + (__v4di) __Z); +} + +#ifdef __DISABLE_AVXIFMA__ +#undef __DISABLE_AVXIFMA__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXIFMA__ */ + +#endif /* _AVXIFMAINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxintrin.h b/template/sysroot/include/avxintrin.h new file mode 100644 index 0000000..8021454 --- /dev/null +++ b/template/sysroot/include/avxintrin.h @@ -0,0 +1,1607 @@ +/* Copyright (C) 2008-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 11.0. */ + +#ifndef _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _AVXINTRIN_H_INCLUDED +#define _AVXINTRIN_H_INCLUDED + +#ifndef __AVX__ +#pragma GCC push_options +#pragma GCC target("avx") +#define __DISABLE_AVX__ +#endif /* __AVX__ */ + +/* Internal data types for implementing the intrinsics. */ +typedef double __v4df __attribute__ ((__vector_size__ (32))); +typedef float __v8sf __attribute__ ((__vector_size__ (32))); +typedef long long __v4di __attribute__ ((__vector_size__ (32))); +typedef unsigned long long __v4du __attribute__ ((__vector_size__ (32))); +typedef int __v8si __attribute__ ((__vector_size__ (32))); +typedef unsigned int __v8su __attribute__ ((__vector_size__ (32))); +typedef short __v16hi __attribute__ ((__vector_size__ (32))); +typedef unsigned short __v16hu __attribute__ ((__vector_size__ (32))); +typedef char __v32qi __attribute__ ((__vector_size__ (32))); +typedef signed char __v32qs __attribute__ ((__vector_size__ (32))); +typedef unsigned char __v32qu __attribute__ ((__vector_size__ (32))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef float __m256 __attribute__ ((__vector_size__ (32), + __may_alias__)); +typedef long long __m256i __attribute__ ((__vector_size__ (32), + __may_alias__)); +typedef double __m256d __attribute__ ((__vector_size__ (32), + __may_alias__)); + +/* Unaligned version of the same types. */ +typedef float __m256_u __attribute__ ((__vector_size__ (32), + __may_alias__, + __aligned__ (1))); +typedef long long __m256i_u __attribute__ ((__vector_size__ (32), + __may_alias__, + __aligned__ (1))); +typedef double __m256d_u __attribute__ ((__vector_size__ (32), + __may_alias__, + __aligned__ (1))); + +/* Compare predicates for scalar and packed compare intrinsics. */ + +/* Equal (ordered, non-signaling) */ +#define _CMP_EQ_OQ 0x00 +/* Less-than (ordered, signaling) */ +#define _CMP_LT_OS 0x01 +/* Less-than-or-equal (ordered, signaling) */ +#define _CMP_LE_OS 0x02 +/* Unordered (non-signaling) */ +#define _CMP_UNORD_Q 0x03 +/* Not-equal (unordered, non-signaling) */ +#define _CMP_NEQ_UQ 0x04 +/* Not-less-than (unordered, signaling) */ +#define _CMP_NLT_US 0x05 +/* Not-less-than-or-equal (unordered, signaling) */ +#define _CMP_NLE_US 0x06 +/* Ordered (nonsignaling) */ +#define _CMP_ORD_Q 0x07 +/* Equal (unordered, non-signaling) */ +#define _CMP_EQ_UQ 0x08 +/* Not-greater-than-or-equal (unordered, signaling) */ +#define _CMP_NGE_US 0x09 +/* Not-greater-than (unordered, signaling) */ +#define _CMP_NGT_US 0x0a +/* False (ordered, non-signaling) */ +#define _CMP_FALSE_OQ 0x0b +/* Not-equal (ordered, non-signaling) */ +#define _CMP_NEQ_OQ 0x0c +/* Greater-than-or-equal (ordered, signaling) */ +#define _CMP_GE_OS 0x0d +/* Greater-than (ordered, signaling) */ +#define _CMP_GT_OS 0x0e +/* True (unordered, non-signaling) */ +#define _CMP_TRUE_UQ 0x0f +/* Equal (ordered, signaling) */ +#define _CMP_EQ_OS 0x10 +/* Less-than (ordered, non-signaling) */ +#define _CMP_LT_OQ 0x11 +/* Less-than-or-equal (ordered, non-signaling) */ +#define _CMP_LE_OQ 0x12 +/* Unordered (signaling) */ +#define _CMP_UNORD_S 0x13 +/* Not-equal (unordered, signaling) */ +#define _CMP_NEQ_US 0x14 +/* Not-less-than (unordered, non-signaling) */ +#define _CMP_NLT_UQ 0x15 +/* Not-less-than-or-equal (unordered, non-signaling) */ +#define _CMP_NLE_UQ 0x16 +/* Ordered (signaling) */ +#define _CMP_ORD_S 0x17 +/* Equal (unordered, signaling) */ +#define _CMP_EQ_US 0x18 +/* Not-greater-than-or-equal (unordered, non-signaling) */ +#define _CMP_NGE_UQ 0x19 +/* Not-greater-than (unordered, non-signaling) */ +#define _CMP_NGT_UQ 0x1a +/* False (ordered, signaling) */ +#define _CMP_FALSE_OS 0x1b +/* Not-equal (ordered, signaling) */ +#define _CMP_NEQ_OS 0x1c +/* Greater-than-or-equal (ordered, non-signaling) */ +#define _CMP_GE_OQ 0x1d +/* Greater-than (ordered, non-signaling) */ +#define _CMP_GT_OQ 0x1e +/* True (unordered, signaling) */ +#define _CMP_TRUE_US 0x1f + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_pd (__m256d __A, __m256d __B) +{ + return (__m256d) ((__v4df)__A + (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_add_ps (__m256 __A, __m256 __B) +{ + return (__m256) ((__v8sf)__A + (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_addsub_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_addsubpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_addsub_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_addsubps256 ((__v8sf)__A, (__v8sf)__B); +} + + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_and_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_andpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_and_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_andps256 ((__v8sf)__A, (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_andnot_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_andnpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_andnot_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_andnps256 ((__v8sf)__A, (__v8sf)__B); +} + +/* Double/single precision floating point blend instructions - select + data from 2 sources using constant/variable mask. */ + +#ifdef __OPTIMIZE__ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blend_pd (__m256d __X, __m256d __Y, const int __M) +{ + return (__m256d) __builtin_ia32_blendpd256 ((__v4df)__X, + (__v4df)__Y, + __M); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blend_ps (__m256 __X, __m256 __Y, const int __M) +{ + return (__m256) __builtin_ia32_blendps256 ((__v8sf)__X, + (__v8sf)__Y, + __M); +} +#else +#define _mm256_blend_pd(X, Y, M) \ + ((__m256d) __builtin_ia32_blendpd256 ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(M))) + +#define _mm256_blend_ps(X, Y, M) \ + ((__m256) __builtin_ia32_blendps256 ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(M))) +#endif + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blendv_pd (__m256d __X, __m256d __Y, __m256d __M) +{ + return (__m256d) __builtin_ia32_blendvpd256 ((__v4df)__X, + (__v4df)__Y, + (__v4df)__M); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_blendv_ps (__m256 __X, __m256 __Y, __m256 __M) +{ + return (__m256) __builtin_ia32_blendvps256 ((__v8sf)__X, + (__v8sf)__Y, + (__v8sf)__M); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_div_pd (__m256d __A, __m256d __B) +{ + return (__m256d) ((__v4df)__A / (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_div_ps (__m256 __A, __m256 __B) +{ + return (__m256) ((__v8sf)__A / (__v8sf)__B); +} + +/* Dot product instructions with mask-defined summing and zeroing parts + of result. */ + +#ifdef __OPTIMIZE__ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dp_ps (__m256 __X, __m256 __Y, const int __M) +{ + return (__m256) __builtin_ia32_dpps256 ((__v8sf)__X, + (__v8sf)__Y, + __M); +} +#else +#define _mm256_dp_ps(X, Y, M) \ + ((__m256) __builtin_ia32_dpps256 ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(M))) +#endif + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hadd_pd (__m256d __X, __m256d __Y) +{ + return (__m256d) __builtin_ia32_haddpd256 ((__v4df)__X, (__v4df)__Y); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hadd_ps (__m256 __X, __m256 __Y) +{ + return (__m256) __builtin_ia32_haddps256 ((__v8sf)__X, (__v8sf)__Y); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hsub_pd (__m256d __X, __m256d __Y) +{ + return (__m256d) __builtin_ia32_hsubpd256 ((__v4df)__X, (__v4df)__Y); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_hsub_ps (__m256 __X, __m256 __Y) +{ + return (__m256) __builtin_ia32_hsubps256 ((__v8sf)__X, (__v8sf)__Y); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_maxpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_max_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_maxps256 ((__v8sf)__A, (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_minpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_min_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_minps256 ((__v8sf)__A, (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mul_pd (__m256d __A, __m256d __B) +{ + return (__m256d) ((__v4df)__A * (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mul_ps (__m256 __A, __m256 __B) +{ + return (__m256) ((__v8sf)__A * (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_or_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_orpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_or_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_orps256 ((__v8sf)__A, (__v8sf)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_pd (__m256d __A, __m256d __B, const int __mask) +{ + return (__m256d) __builtin_ia32_shufpd256 ((__v4df)__A, (__v4df)__B, + __mask); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_shuffle_ps (__m256 __A, __m256 __B, const int __mask) +{ + return (__m256) __builtin_ia32_shufps256 ((__v8sf)__A, (__v8sf)__B, + __mask); +} +#else +#define _mm256_shuffle_pd(A, B, N) \ + ((__m256d)__builtin_ia32_shufpd256 ((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(N))) + +#define _mm256_shuffle_ps(A, B, N) \ + ((__m256) __builtin_ia32_shufps256 ((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(N))) +#endif + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_pd (__m256d __A, __m256d __B) +{ + return (__m256d) ((__v4df)__A - (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sub_ps (__m256 __A, __m256 __B) +{ + return (__m256) ((__v8sf)__A - (__v8sf)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_xor_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_xorpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_xor_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_xorps256 ((__v8sf)__A, (__v8sf)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_pd (__m128d __X, __m128d __Y, const int __P) +{ + return (__m128d) __builtin_ia32_cmppd ((__v2df)__X, (__v2df)__Y, __P); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ps (__m128 __X, __m128 __Y, const int __P) +{ + return (__m128) __builtin_ia32_cmpps ((__v4sf)__X, (__v4sf)__Y, __P); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_pd (__m256d __X, __m256d __Y, const int __P) +{ + return (__m256d) __builtin_ia32_cmppd256 ((__v4df)__X, (__v4df)__Y, + __P); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmp_ps (__m256 __X, __m256 __Y, const int __P) +{ + return (__m256) __builtin_ia32_cmpps256 ((__v8sf)__X, (__v8sf)__Y, + __P); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_sd (__m128d __X, __m128d __Y, const int __P) +{ + return (__m128d) __builtin_ia32_cmpsd ((__v2df)__X, (__v2df)__Y, __P); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmp_ss (__m128 __X, __m128 __Y, const int __P) +{ + return (__m128) __builtin_ia32_cmpss ((__v4sf)__X, (__v4sf)__Y, __P); +} +#else +#define _mm_cmp_pd(X, Y, P) \ + ((__m128d) __builtin_ia32_cmppd ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P))) + +#define _mm_cmp_ps(X, Y, P) \ + ((__m128) __builtin_ia32_cmpps ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P))) + +#define _mm256_cmp_pd(X, Y, P) \ + ((__m256d) __builtin_ia32_cmppd256 ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), (int)(P))) + +#define _mm256_cmp_ps(X, Y, P) \ + ((__m256) __builtin_ia32_cmpps256 ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), (int)(P))) + +#define _mm_cmp_sd(X, Y, P) \ + ((__m128d) __builtin_ia32_cmpsd ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(P))) + +#define _mm_cmp_ss(X, Y, P) \ + ((__m128) __builtin_ia32_cmpss ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(P))) +#endif + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsi256_si32 (__m256i __A) +{ + __v8si __B = (__v8si) __A; + return __B[0]; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_pd (__m128i __A) +{ + return (__m256d)__builtin_ia32_cvtdq2pd256 ((__v4si) __A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtepi32_ps (__m256i __A) +{ + return (__m256)__builtin_ia32_cvtdq2ps256 ((__v8si) __A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_ps (__m256d __A) +{ + return (__m128)__builtin_ia32_cvtpd2ps256 ((__v4df) __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_epi32 (__m256 __A) +{ + return (__m256i)__builtin_ia32_cvtps2dq256 ((__v8sf) __A); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_pd (__m128 __A) +{ + return (__m256d)__builtin_ia32_cvtps2pd256 ((__v4sf) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttpd_epi32 (__m256d __A) +{ + return (__m128i)__builtin_ia32_cvttpd2dq256 ((__v4df) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtpd_epi32 (__m256d __A) +{ + return (__m128i)__builtin_ia32_cvtpd2dq256 ((__v4df) __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvttps_epi32 (__m256 __A) +{ + return (__m256i)__builtin_ia32_cvttps2dq256 ((__v8sf) __A); +} + +extern __inline double +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtsd_f64 (__m256d __A) +{ + return __A[0]; +} + +extern __inline float +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtss_f32 (__m256 __A) +{ + return __A[0]; +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extractf128_pd (__m256d __X, const int __N) +{ + return (__m128d) __builtin_ia32_vextractf128_pd256 ((__v4df)__X, __N); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extractf128_ps (__m256 __X, const int __N) +{ + return (__m128) __builtin_ia32_vextractf128_ps256 ((__v8sf)__X, __N); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extractf128_si256 (__m256i __X, const int __N) +{ + return (__m128i) __builtin_ia32_vextractf128_si256 ((__v8si)__X, __N); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extract_epi32 (__m256i __X, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 2); + return _mm_extract_epi32 (__Y, __N % 4); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extract_epi16 (__m256i __X, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 3); + return _mm_extract_epi16 (__Y, __N % 8); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extract_epi8 (__m256i __X, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 4); + return _mm_extract_epi8 (__Y, __N % 16); +} + +#ifdef __x86_64__ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_extract_epi64 (__m256i __X, const int __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 1); + return _mm_extract_epi64 (__Y, __N % 2); +} +#endif +#else +#define _mm256_extractf128_pd(X, N) \ + ((__m128d) __builtin_ia32_vextractf128_pd256 ((__v4df)(__m256d)(X), \ + (int)(N))) + +#define _mm256_extractf128_ps(X, N) \ + ((__m128) __builtin_ia32_vextractf128_ps256 ((__v8sf)(__m256)(X), \ + (int)(N))) + +#define _mm256_extractf128_si256(X, N) \ + ((__m128i) __builtin_ia32_vextractf128_si256 ((__v8si)(__m256i)(X), \ + (int)(N))) + +#define _mm256_extract_epi32(X, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 2); \ + _mm_extract_epi32 (__Y, (N) % 4); \ + })) + +#define _mm256_extract_epi16(X, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 3); \ + _mm_extract_epi16 (__Y, (N) % 8); \ + })) + +#define _mm256_extract_epi8(X, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 4); \ + _mm_extract_epi8 (__Y, (N) % 16); \ + })) + +#ifdef __x86_64__ +#define _mm256_extract_epi64(X, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 1); \ + _mm_extract_epi64 (__Y, (N) % 2); \ + })) +#endif +#endif + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zeroall (void) +{ + __builtin_ia32_vzeroall (); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zeroupper (void) +{ + __builtin_ia32_vzeroupper (); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutevar_pd (__m128d __A, __m128i __C) +{ + return (__m128d) __builtin_ia32_vpermilvarpd ((__v2df)__A, + (__v2di)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutevar_pd (__m256d __A, __m256i __C) +{ + return (__m256d) __builtin_ia32_vpermilvarpd256 ((__v4df)__A, + (__v4di)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permutevar_ps (__m128 __A, __m128i __C) +{ + return (__m128) __builtin_ia32_vpermilvarps ((__v4sf)__A, + (__v4si)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permutevar_ps (__m256 __A, __m256i __C) +{ + return (__m256) __builtin_ia32_vpermilvarps256 ((__v8sf)__A, + (__v8si)__C); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permute_pd (__m128d __X, const int __C) +{ + return (__m128d) __builtin_ia32_vpermilpd ((__v2df)__X, __C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute_pd (__m256d __X, const int __C) +{ + return (__m256d) __builtin_ia32_vpermilpd256 ((__v4df)__X, __C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permute_ps (__m128 __X, const int __C) +{ + return (__m128) __builtin_ia32_vpermilps ((__v4sf)__X, __C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute_ps (__m256 __X, const int __C) +{ + return (__m256) __builtin_ia32_vpermilps256 ((__v8sf)__X, __C); +} +#else +#define _mm_permute_pd(X, C) \ + ((__m128d) __builtin_ia32_vpermilpd ((__v2df)(__m128d)(X), (int)(C))) + +#define _mm256_permute_pd(X, C) \ + ((__m256d) __builtin_ia32_vpermilpd256 ((__v4df)(__m256d)(X), (int)(C))) + +#define _mm_permute_ps(X, C) \ + ((__m128) __builtin_ia32_vpermilps ((__v4sf)(__m128)(X), (int)(C))) + +#define _mm256_permute_ps(X, C) \ + ((__m256) __builtin_ia32_vpermilps256 ((__v8sf)(__m256)(X), (int)(C))) +#endif + +#ifdef __OPTIMIZE__ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2f128_pd (__m256d __X, __m256d __Y, const int __C) +{ + return (__m256d) __builtin_ia32_vperm2f128_pd256 ((__v4df)__X, + (__v4df)__Y, + __C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2f128_ps (__m256 __X, __m256 __Y, const int __C) +{ + return (__m256) __builtin_ia32_vperm2f128_ps256 ((__v8sf)__X, + (__v8sf)__Y, + __C); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2f128_si256 (__m256i __X, __m256i __Y, const int __C) +{ + return (__m256i) __builtin_ia32_vperm2f128_si256 ((__v8si)__X, + (__v8si)__Y, + __C); +} +#else +#define _mm256_permute2f128_pd(X, Y, C) \ + ((__m256d) __builtin_ia32_vperm2f128_pd256 ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), \ + (int)(C))) + +#define _mm256_permute2f128_ps(X, Y, C) \ + ((__m256) __builtin_ia32_vperm2f128_ps256 ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), \ + (int)(C))) + +#define _mm256_permute2f128_si256(X, Y, C) \ + ((__m256i) __builtin_ia32_vperm2f128_si256 ((__v8si)(__m256i)(X), \ + (__v8si)(__m256i)(Y), \ + (int)(C))) +#endif + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_broadcast_ss (float const *__X) +{ + return (__m128) __builtin_ia32_vbroadcastss (__X); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_sd (double const *__X) +{ + return (__m256d) __builtin_ia32_vbroadcastsd256 (__X); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_ss (float const *__X) +{ + return (__m256) __builtin_ia32_vbroadcastss256 (__X); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_pd (__m128d const *__X) +{ + return (__m256d) __builtin_ia32_vbroadcastf128_pd256 (__X); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_broadcast_ps (__m128 const *__X) +{ + return (__m256) __builtin_ia32_vbroadcastf128_ps256 (__X); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insertf128_pd (__m256d __X, __m128d __Y, const int __O) +{ + return (__m256d) __builtin_ia32_vinsertf128_pd256 ((__v4df)__X, + (__v2df)__Y, + __O); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insertf128_ps (__m256 __X, __m128 __Y, const int __O) +{ + return (__m256) __builtin_ia32_vinsertf128_ps256 ((__v8sf)__X, + (__v4sf)__Y, + __O); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insertf128_si256 (__m256i __X, __m128i __Y, const int __O) +{ + return (__m256i) __builtin_ia32_vinsertf128_si256 ((__v8si)__X, + (__v4si)__Y, + __O); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insert_epi32 (__m256i __X, int __D, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 2); + __Y = _mm_insert_epi32 (__Y, __D, __N % 4); + return _mm256_insertf128_si256 (__X, __Y, __N >> 2); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insert_epi16 (__m256i __X, int __D, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 3); + __Y = _mm_insert_epi16 (__Y, __D, __N % 8); + return _mm256_insertf128_si256 (__X, __Y, __N >> 3); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insert_epi8 (__m256i __X, int __D, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 4); + __Y = _mm_insert_epi8 (__Y, __D, __N % 16); + return _mm256_insertf128_si256 (__X, __Y, __N >> 4); +} + +#ifdef __x86_64__ +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_insert_epi64 (__m256i __X, long long __D, int const __N) +{ + __m128i __Y = _mm256_extractf128_si256 (__X, __N >> 1); + __Y = _mm_insert_epi64 (__Y, __D, __N % 2); + return _mm256_insertf128_si256 (__X, __Y, __N >> 1); +} +#endif +#else +#define _mm256_insertf128_pd(X, Y, O) \ + ((__m256d) __builtin_ia32_vinsertf128_pd256 ((__v4df)(__m256d)(X), \ + (__v2df)(__m128d)(Y), \ + (int)(O))) + +#define _mm256_insertf128_ps(X, Y, O) \ + ((__m256) __builtin_ia32_vinsertf128_ps256 ((__v8sf)(__m256)(X), \ + (__v4sf)(__m128)(Y), \ + (int)(O))) + +#define _mm256_insertf128_si256(X, Y, O) \ + ((__m256i) __builtin_ia32_vinsertf128_si256 ((__v8si)(__m256i)(X), \ + (__v4si)(__m128i)(Y), \ + (int)(O))) + +#define _mm256_insert_epi32(X, D, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 2); \ + __Y = _mm_insert_epi32 (__Y, (D), (N) % 4); \ + _mm256_insertf128_si256 ((X), __Y, (N) >> 2); \ + })) + +#define _mm256_insert_epi16(X, D, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 3); \ + __Y = _mm_insert_epi16 (__Y, (D), (N) % 8); \ + _mm256_insertf128_si256 ((X), __Y, (N) >> 3); \ + })) + +#define _mm256_insert_epi8(X, D, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 4); \ + __Y = _mm_insert_epi8 (__Y, (D), (N) % 16); \ + _mm256_insertf128_si256 ((X), __Y, (N) >> 4); \ + })) + +#ifdef __x86_64__ +#define _mm256_insert_epi64(X, D, N) \ + (__extension__ \ + ({ \ + __m128i __Y = _mm256_extractf128_si256 ((X), (N) >> 1); \ + __Y = _mm_insert_epi64 (__Y, (D), (N) % 2); \ + _mm256_insertf128_si256 ((X), __Y, (N) >> 1); \ + })) +#endif +#endif + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_pd (double const *__P) +{ + return *(__m256d *)__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_pd (double *__P, __m256d __A) +{ + *(__m256d *)__P = __A; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_ps (float const *__P) +{ + return *(__m256 *)__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_ps (float *__P, __m256 __A) +{ + *(__m256 *)__P = __A; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_pd (double const *__P) +{ + return *(__m256d_u *)__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_pd (double *__P, __m256d __A) +{ + *(__m256d_u *)__P = __A; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_ps (float const *__P) +{ + return *(__m256_u *)__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_ps (float *__P, __m256 __A) +{ + *(__m256_u *)__P = __A; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_load_si256 (__m256i const *__P) +{ + return *__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_store_si256 (__m256i *__P, __m256i __A) +{ + *__P = __A; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu_si256 (__m256i_u const *__P) +{ + return *__P; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_si256 (__m256i_u *__P, __m256i __A) +{ + *__P = __A; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskload_pd (double const *__P, __m128i __M) +{ + return (__m128d) __builtin_ia32_maskloadpd ((const __v2df *)__P, + (__v2di)__M); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskstore_pd (double *__P, __m128i __M, __m128d __A) +{ + __builtin_ia32_maskstorepd ((__v2df *)__P, (__v2di)__M, (__v2df)__A); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskload_pd (double const *__P, __m256i __M) +{ + return (__m256d) __builtin_ia32_maskloadpd256 ((const __v4df *)__P, + (__v4di)__M); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskstore_pd (double *__P, __m256i __M, __m256d __A) +{ + __builtin_ia32_maskstorepd256 ((__v4df *)__P, (__v4di)__M, (__v4df)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskload_ps (float const *__P, __m128i __M) +{ + return (__m128) __builtin_ia32_maskloadps ((const __v4sf *)__P, + (__v4si)__M); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskstore_ps (float *__P, __m128i __M, __m128 __A) +{ + __builtin_ia32_maskstoreps ((__v4sf *)__P, (__v4si)__M, (__v4sf)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskload_ps (float const *__P, __m256i __M) +{ + return (__m256) __builtin_ia32_maskloadps256 ((const __v8sf *)__P, + (__v8si)__M); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskstore_ps (float *__P, __m256i __M, __m256 __A) +{ + __builtin_ia32_maskstoreps256 ((__v8sf *)__P, (__v8si)__M, (__v8sf)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movehdup_ps (__m256 __X) +{ + return (__m256) __builtin_ia32_movshdup256 ((__v8sf)__X); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_moveldup_ps (__m256 __X) +{ + return (__m256) __builtin_ia32_movsldup256 ((__v8sf)__X); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movedup_pd (__m256d __X) +{ + return (__m256d) __builtin_ia32_movddup256 ((__v4df)__X); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_lddqu_si256 (__m256i const *__P) +{ + return (__m256i) __builtin_ia32_lddqu256 ((char const *)__P); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_stream_si256 (__m256i *__A, __m256i __B) +{ + __builtin_ia32_movntdq256 ((__v4di *)__A, (__v4di)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_stream_pd (double *__A, __m256d __B) +{ + __builtin_ia32_movntpd256 (__A, (__v4df)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_stream_ps (float *__P, __m256 __A) +{ + __builtin_ia32_movntps256 (__P, (__v8sf)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rcp_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_rcpps256 ((__v8sf)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_rsqrt_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_rsqrtps256 ((__v8sf)__A); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sqrt_pd (__m256d __A) +{ + return (__m256d) __builtin_ia32_sqrtpd256 ((__v4df)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sqrt_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_sqrtps256 ((__v8sf)__A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_round_pd (__m256d __V, const int __M) +{ + return (__m256d) __builtin_ia32_roundpd256 ((__v4df)__V, __M); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_round_ps (__m256 __V, const int __M) +{ + return (__m256) __builtin_ia32_roundps256 ((__v8sf)__V, __M); +} +#else +#define _mm256_round_pd(V, M) \ + ((__m256d) __builtin_ia32_roundpd256 ((__v4df)(__m256d)(V), (int)(M))) + +#define _mm256_round_ps(V, M) \ + ((__m256) __builtin_ia32_roundps256 ((__v8sf)(__m256)(V), (int)(M))) +#endif + +#define _mm256_ceil_pd(V) _mm256_round_pd ((V), _MM_FROUND_CEIL) +#define _mm256_floor_pd(V) _mm256_round_pd ((V), _MM_FROUND_FLOOR) +#define _mm256_ceil_ps(V) _mm256_round_ps ((V), _MM_FROUND_CEIL) +#define _mm256_floor_ps(V) _mm256_round_ps ((V), _MM_FROUND_FLOOR) + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_unpckhpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_pd (__m256d __A, __m256d __B) +{ + return (__m256d) __builtin_ia32_unpcklpd256 ((__v4df)__A, (__v4df)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpackhi_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_unpckhps256 ((__v8sf)__A, (__v8sf)__B); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_unpacklo_ps (__m256 __A, __m256 __B) +{ + return (__m256) __builtin_ia32_unpcklps256 ((__v8sf)__A, (__v8sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testz_pd (__m128d __M, __m128d __V) +{ + return __builtin_ia32_vtestzpd ((__v2df)__M, (__v2df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testc_pd (__m128d __M, __m128d __V) +{ + return __builtin_ia32_vtestcpd ((__v2df)__M, (__v2df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testnzc_pd (__m128d __M, __m128d __V) +{ + return __builtin_ia32_vtestnzcpd ((__v2df)__M, (__v2df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testz_ps (__m128 __M, __m128 __V) +{ + return __builtin_ia32_vtestzps ((__v4sf)__M, (__v4sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testc_ps (__m128 __M, __m128 __V) +{ + return __builtin_ia32_vtestcps ((__v4sf)__M, (__v4sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testnzc_ps (__m128 __M, __m128 __V) +{ + return __builtin_ia32_vtestnzcps ((__v4sf)__M, (__v4sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testz_pd (__m256d __M, __m256d __V) +{ + return __builtin_ia32_vtestzpd256 ((__v4df)__M, (__v4df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testc_pd (__m256d __M, __m256d __V) +{ + return __builtin_ia32_vtestcpd256 ((__v4df)__M, (__v4df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testnzc_pd (__m256d __M, __m256d __V) +{ + return __builtin_ia32_vtestnzcpd256 ((__v4df)__M, (__v4df)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testz_ps (__m256 __M, __m256 __V) +{ + return __builtin_ia32_vtestzps256 ((__v8sf)__M, (__v8sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testc_ps (__m256 __M, __m256 __V) +{ + return __builtin_ia32_vtestcps256 ((__v8sf)__M, (__v8sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testnzc_ps (__m256 __M, __m256 __V) +{ + return __builtin_ia32_vtestnzcps256 ((__v8sf)__M, (__v8sf)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testz_si256 (__m256i __M, __m256i __V) +{ + return __builtin_ia32_ptestz256 ((__v4di)__M, (__v4di)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testc_si256 (__m256i __M, __m256i __V) +{ + return __builtin_ia32_ptestc256 ((__v4di)__M, (__v4di)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_testnzc_si256 (__m256i __M, __m256i __V) +{ + return __builtin_ia32_ptestnzc256 ((__v4di)__M, (__v4di)__V); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movemask_pd (__m256d __A) +{ + return __builtin_ia32_movmskpd256 ((__v4df)__A); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_movemask_ps (__m256 __A) +{ + return __builtin_ia32_movmskps256 ((__v8sf)__A); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_undefined_pd (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256d __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_undefined_ps (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256 __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_undefined_si256 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m256i __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setzero_pd (void) +{ + return __extension__ (__m256d){ 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setzero_ps (void) +{ + return __extension__ (__m256){ 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setzero_si256 (void) +{ + return __extension__ (__m256i)(__v4di){ 0, 0, 0, 0 }; +} + +/* Create the vector [A B C D]. */ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_pd (double __A, double __B, double __C, double __D) +{ + return __extension__ (__m256d){ __D, __C, __B, __A }; +} + +/* Create the vector [A B C D E F G H]. */ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_ps (float __A, float __B, float __C, float __D, + float __E, float __F, float __G, float __H) +{ + return __extension__ (__m256){ __H, __G, __F, __E, + __D, __C, __B, __A }; +} + +/* Create the vector [A B C D E F G H]. */ +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_epi32 (int __A, int __B, int __C, int __D, + int __E, int __F, int __G, int __H) +{ + return __extension__ (__m256i)(__v8si){ __H, __G, __F, __E, + __D, __C, __B, __A }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_epi16 (short __q15, short __q14, short __q13, short __q12, + short __q11, short __q10, short __q09, short __q08, + short __q07, short __q06, short __q05, short __q04, + short __q03, short __q02, short __q01, short __q00) +{ + return __extension__ (__m256i)(__v16hi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15 + }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_epi8 (char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return __extension__ (__m256i)(__v32qi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15, + __q16, __q17, __q18, __q19, __q20, __q21, __q22, __q23, + __q24, __q25, __q26, __q27, __q28, __q29, __q30, __q31 + }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_epi64x (long long __A, long long __B, long long __C, + long long __D) +{ + return __extension__ (__m256i)(__v4di){ __D, __C, __B, __A }; +} + +/* Create a vector with all elements equal to A. */ +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_pd (double __A) +{ + return __extension__ (__m256d){ __A, __A, __A, __A }; +} + +/* Create a vector with all elements equal to A. */ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_ps (float __A) +{ + return __extension__ (__m256){ __A, __A, __A, __A, + __A, __A, __A, __A }; +} + +/* Create a vector with all elements equal to A. */ +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_epi32 (int __A) +{ + return __extension__ (__m256i)(__v8si){ __A, __A, __A, __A, + __A, __A, __A, __A }; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_epi16 (short __A) +{ + return _mm256_set_epi16 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_epi8 (char __A) +{ + return _mm256_set_epi8 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_epi64x (long long __A) +{ + return __extension__ (__m256i)(__v4di){ __A, __A, __A, __A }; +} + +/* Create vectors of elements in the reversed order from the + _mm256_set_XXX functions. */ + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_pd (double __A, double __B, double __C, double __D) +{ + return _mm256_set_pd (__D, __C, __B, __A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_ps (float __A, float __B, float __C, float __D, + float __E, float __F, float __G, float __H) +{ + return _mm256_set_ps (__H, __G, __F, __E, __D, __C, __B, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_epi32 (int __A, int __B, int __C, int __D, + int __E, int __F, int __G, int __H) +{ + return _mm256_set_epi32 (__H, __G, __F, __E, __D, __C, __B, __A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_epi16 (short __q15, short __q14, short __q13, short __q12, + short __q11, short __q10, short __q09, short __q08, + short __q07, short __q06, short __q05, short __q04, + short __q03, short __q02, short __q01, short __q00) +{ + return _mm256_set_epi16 (__q00, __q01, __q02, __q03, + __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, + __q12, __q13, __q14, __q15); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_epi8 (char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return _mm256_set_epi8 (__q00, __q01, __q02, __q03, + __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, + __q12, __q13, __q14, __q15, + __q16, __q17, __q18, __q19, + __q20, __q21, __q22, __q23, + __q24, __q25, __q26, __q27, + __q28, __q29, __q30, __q31); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_epi64x (long long __A, long long __B, long long __C, + long long __D) +{ + return _mm256_set_epi64x (__D, __C, __B, __A); +} + +/* Casts between various SP, DP, INT vector types. Note that these do no + conversion of values, they just change the type. */ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castpd_ps (__m256d __A) +{ + return (__m256) __A; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castpd_si256 (__m256d __A) +{ + return (__m256i) __A; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castps_pd (__m256 __A) +{ + return (__m256d) __A; +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castps_si256(__m256 __A) +{ + return (__m256i) __A; +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castsi256_ps (__m256i __A) +{ + return (__m256) __A; +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castsi256_pd (__m256i __A) +{ + return (__m256d) __A; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castpd256_pd128 (__m256d __A) +{ + return (__m128d) __builtin_ia32_pd_pd256 ((__v4df)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castps256_ps128 (__m256 __A) +{ + return (__m128) __builtin_ia32_ps_ps256 ((__v8sf)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castsi256_si128 (__m256i __A) +{ + return (__m128i) __builtin_ia32_si_si256 ((__v8si)__A); +} + +/* When cast is done from a 128 to 256-bit type, the low 128 bits of + the 256-bit result contain source parameter value and the upper 128 + bits of the result are undefined. Those intrinsics shouldn't + generate any extra moves. */ + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castpd128_pd256 (__m128d __A) +{ + return (__m256d) __builtin_ia32_pd256_pd ((__v2df)__A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castps128_ps256 (__m128 __A) +{ + return (__m256) __builtin_ia32_ps256_ps ((__v4sf)__A); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_castsi128_si256 (__m128i __A) +{ + return (__m256i) __builtin_ia32_si256_si ((__v4si)__A); +} + +/* Similarly, but with zero extension instead of undefined values. */ + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zextpd128_pd256 (__m128d __A) +{ + return _mm256_insertf128_pd (_mm256_setzero_pd (), __A, 0); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zextps128_ps256 (__m128 __A) +{ + return _mm256_insertf128_ps (_mm256_setzero_ps (), __A, 0); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_zextsi128_si256 (__m128i __A) +{ + return _mm256_insertf128_si256 (_mm256_setzero_si256 (), __A, 0); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_m128 ( __m128 __H, __m128 __L) +{ + return _mm256_insertf128_ps (_mm256_castps128_ps256 (__L), __H, 1); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_m128d (__m128d __H, __m128d __L) +{ + return _mm256_insertf128_pd (_mm256_castpd128_pd256 (__L), __H, 1); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set_m128i (__m128i __H, __m128i __L) +{ + return _mm256_insertf128_si256 (_mm256_castsi128_si256 (__L), __H, 1); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_m128 (__m128 __L, __m128 __H) +{ + return _mm256_set_m128 (__H, __L); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_m128d (__m128d __L, __m128d __H) +{ + return _mm256_set_m128d (__H, __L); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_setr_m128i (__m128i __L, __m128i __H) +{ + return _mm256_set_m128i (__H, __L); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu2_m128 (float const *__PH, float const *__PL) +{ + return _mm256_insertf128_ps (_mm256_castps128_ps256 (_mm_loadu_ps (__PL)), + _mm_loadu_ps (__PH), 1); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu2_m128 (float *__PH, float *__PL, __m256 __A) +{ + _mm_storeu_ps (__PL, _mm256_castps256_ps128 (__A)); + _mm_storeu_ps (__PH, _mm256_extractf128_ps (__A, 1)); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu2_m128d (double const *__PH, double const *__PL) +{ + return _mm256_insertf128_pd (_mm256_castpd128_pd256 (_mm_loadu_pd (__PL)), + _mm_loadu_pd (__PH), 1); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu2_m128d (double *__PH, double *__PL, __m256d __A) +{ + _mm_storeu_pd (__PL, _mm256_castpd256_pd128 (__A)); + _mm_storeu_pd (__PH, _mm256_extractf128_pd (__A, 1)); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_loadu2_m128i (__m128i_u const *__PH, __m128i_u const *__PL) +{ + return _mm256_insertf128_si256 (_mm256_castsi128_si256 (_mm_loadu_si128 (__PL)), + _mm_loadu_si128 (__PH), 1); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu2_m128i (__m128i_u *__PH, __m128i_u *__PL, __m256i __A) +{ + _mm_storeu_si128 (__PL, _mm256_castsi256_si128 (__A)); + _mm_storeu_si128 (__PH, _mm256_extractf128_si256 (__A, 1)); +} + +#ifdef __DISABLE_AVX__ +#undef __DISABLE_AVX__ +#pragma GCC pop_options +#endif /* __DISABLE_AVX__ */ + +#endif /* _AVXINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxneconvertintrin.h b/template/sysroot/include/avxneconvertintrin.h new file mode 100644 index 0000000..50c7939 --- /dev/null +++ b/template/sysroot/include/avxneconvertintrin.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2021-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXNECONVERTINTRIN_H_INCLUDED +#define _AVXNECONVERTINTRIN_H_INCLUDED + +#ifndef __AVXNECONVERT__ +#pragma GCC push_options +#pragma GCC target ("avxneconvert") +#define __DISABLE_AVXNECONVERT__ +#endif /* __AVXNECONVERT__ */ + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bcstnebf16_ps (const void *__P) +{ + return (__m128) __builtin_ia32_vbcstnebf162ps128 ((const __bf16 *) __P); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bcstnebf16_ps (const void *__P) +{ + return (__m256) __builtin_ia32_vbcstnebf162ps256 ((const __bf16 *) __P); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bcstnesh_ps (const void *__P) +{ + return (__m128) __builtin_ia32_vbcstnesh2ps128 ((const _Float16 *) __P); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bcstnesh_ps (const void *__P) +{ + return (__m256) __builtin_ia32_vbcstnesh2ps256 ((const _Float16 *) __P); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneebf16_ps (const __m128bh *__A) +{ + return (__m128) __builtin_ia32_vcvtneebf162ps128 ((const __v8bf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneebf16_ps (const __m256bh *__A) +{ + return (__m256) __builtin_ia32_vcvtneebf162ps256 ((const __v16bf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneeph_ps (const __m128h *__A) +{ + return (__m128) __builtin_ia32_vcvtneeph2ps128 ((const __v8hf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneeph_ps (const __m256h *__A) +{ + return (__m256) __builtin_ia32_vcvtneeph2ps256 ((const __v16hf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneobf16_ps (const __m128bh *__A) +{ + return (__m128) __builtin_ia32_vcvtneobf162ps128 ((const __v8bf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneobf16_ps (const __m256bh *__A) +{ + return (__m256) __builtin_ia32_vcvtneobf162ps256 ((const __v16bf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneoph_ps (const __m128h *__A) +{ + return (__m128) __builtin_ia32_vcvtneoph2ps128 ((const __v8hf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneoph_ps (const __m256h *__A) +{ + return (__m256) __builtin_ia32_vcvtneoph2ps256 ((const __v16hf *) __A); +} + +extern __inline __m128bh +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneps_avx_pbh (__m128 __A) +{ + return (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (__A); +} + +extern __inline __m128bh +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneps_avx_pbh (__m256 __A) +{ + return (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (__A); +} + +#ifdef __DISABLE_AVXNECONVERT__ +#undef __DISABLE_AVXNECONVERT__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXNECONVERT__ */ + +#endif /* _AVXNECONVERTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxvnniint16intrin.h b/template/sysroot/include/avxvnniint16intrin.h new file mode 100644 index 0000000..f26c313 --- /dev/null +++ b/template/sysroot/include/avxvnniint16intrin.h @@ -0,0 +1,138 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXVNNIINT16INTRIN_H_INCLUDED +#define _AVXVNNIINT16INTRIN_H_INCLUDED + +#if !defined(__AVXVNNIINT16__) +#pragma GCC push_options +#pragma GCC target("avxvnniint16") +#define __DISABLE_AVXVNNIINT16__ +#endif /* __AVXVNNIINT16__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwsud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwsuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwusd_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwusd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwusds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwusds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwuud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwuuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpwuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwsud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwsuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwusd_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwusd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwusds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwusds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwuud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwuuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpwuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +#ifdef __DISABLE_AVXVNNIINT16__ +#undef __DISABLE_AVXVNNIINT16__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXVNNIINT16__ */ + +#endif /* __AVXVNNIINT16INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxvnniint8intrin.h b/template/sysroot/include/avxvnniint8intrin.h new file mode 100644 index 0000000..f72e3b3 --- /dev/null +++ b/template/sysroot/include/avxvnniint8intrin.h @@ -0,0 +1,138 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXVNNIINT8INTRIN_H_INCLUDED +#define _AVXVNNIINT8INTRIN_H_INCLUDED + +#if !defined(__AVXVNNIINT8__) +#pragma GCC push_options +#pragma GCC target("avxvnniint8") +#define __DISABLE_AVXVNNIINT8__ +#endif /* __AVXVNNIINT8__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbssd_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbssd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbssds_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbssds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbsud_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbsuds_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbuud_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbuuds_epi32 (__m128i __W, __m128i __A, __m128i __B) +{ + return (__m128i) + __builtin_ia32_vpdpbuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbssd_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbssd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbssds_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbssds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbsud_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbsuds_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbuud_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbuuds_epi32 (__m256i __W, __m256i __A, __m256i __B) +{ + return (__m256i) + __builtin_ia32_vpdpbuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B); +} + +#ifdef __DISABLE_AVXVNNIINT8__ +#undef __DISABLE_AVXVNNIINT8__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXVNNIINT8__ */ + +#endif /* __AVXVNNIINT8INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/avxvnniintrin.h b/template/sysroot/include/avxvnniintrin.h new file mode 100644 index 0000000..f085e53 --- /dev/null +++ b/template/sysroot/include/avxvnniintrin.h @@ -0,0 +1,113 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXVNNIINTRIN_H_INCLUDED +#define _AVXVNNIINTRIN_H_INCLUDED + +#if !defined(__AVXVNNI__) +#pragma GCC push_options +#pragma GCC target("avxvnni") +#define __DISABLE_AVXVNNIVL__ +#endif /* __AVXVNNIVL__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbusd_avx_epi32(__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) __A, + (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbusd_avx_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) __A, + (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpbusds_avx_epi32(__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) __A, + (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpbusds_avx_epi32(__m128i __A,__m128i __B,__m128i __C) +{ + return (__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) __A, + (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwssd_avx_epi32(__m256i __A,__m256i __B,__m256i __C) +{ + return (__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) __A, + (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwssd_avx_epi32(__m128i __A,__m128i __B,__m128i __C) +{ + return (__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) __A, + (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_dpwssds_avx_epi32(__m256i __A,__m256i __B,__m256i __C) +{ + return (__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) __A, + (__v8si) __B, + (__v8si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dpwssds_avx_epi32(__m128i __A,__m128i __B,__m128i __C) +{ + return (__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) __A, + (__v4si) __B, + (__v4si) __C); +} + +#ifdef __DISABLE_AVXVNNIVL__ +#undef __DISABLE_AVXVNNIVL__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXVNNIVL__ */ +#endif /* _AVXVNNIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/backward/auto_ptr.h b/template/sysroot/include/backward/auto_ptr.h new file mode 100644 index 0000000..dccd459 --- /dev/null +++ b/template/sysroot/include/backward/auto_ptr.h @@ -0,0 +1,343 @@ +// auto_ptr implementation -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file backward/auto_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _BACKWARD_AUTO_PTR_H +#define _BACKWARD_AUTO_PTR_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * A wrapper class to provide auto_ptr with reference semantics. + * For example, an auto_ptr can be assigned (or constructed from) + * the result of a function which returns an auto_ptr by value. + * + * All the auto_ptr_ref stuff should happen behind the scenes. + */ + template + struct auto_ptr_ref + { + _Tp1* _M_ptr; + + explicit + auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { } + } _GLIBCXX11_DEPRECATED; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /** + * @brief A simple smart pointer providing strict ownership semantics. + * + * The Standard says: + *
    +   *  An @c auto_ptr owns the object it holds a pointer to.  Copying
    +   *  an @c auto_ptr copies the pointer and transfers ownership to the
    +   *  destination.  If more than one @c auto_ptr owns the same object
    +   *  at the same time the behavior of the program is undefined.
    +   *
    +   *  The uses of @c auto_ptr include providing temporary
    +   *  exception-safety for dynamically allocated memory, passing
    +   *  ownership of dynamically allocated memory to a function, and
    +   *  returning dynamically allocated memory from a function.  @c
    +   *  auto_ptr does not meet the CopyConstructible and Assignable
    +   *  requirements for Standard Library container elements and thus
    +   *  instantiating a Standard Library container with an @c auto_ptr
    +   *  results in undefined behavior.
    +   *  
    + * Quoted from [20.4.5]/3. + * + * Good examples of what can and cannot be done with auto_ptr can + * be found in the libstdc++ testsuite. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * 127. auto_ptr<> conversion issues + * These resolutions have all been incorporated. + * + * @headerfile memory + * @deprecated Deprecated in C++11, no longer in the standard since C++17. + * Use `unique_ptr` instead. + */ + template + class auto_ptr + { + private: + _Tp* _M_ptr; + + public: + /// The pointed-to type. + typedef _Tp element_type; + + /** + * @brief An %auto_ptr is usually constructed from a raw pointer. + * @param __p A pointer (defaults to NULL). + * + * This object now @e owns the object pointed to by @a __p. + */ + explicit + auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } + + /** + * @brief An %auto_ptr can be constructed from another %auto_ptr. + * @param __a Another %auto_ptr of the same type. + * + * This object now @e owns the object previously owned by @a __a, + * which has given up ownership. + */ + auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { } + + /** + * @brief An %auto_ptr can be constructed from another %auto_ptr. + * @param __a Another %auto_ptr of a different but related type. + * + * A pointer-to-Tp1 must be convertible to a + * pointer-to-Tp/element_type. + * + * This object now @e owns the object previously owned by @a __a, + * which has given up ownership. + */ + template + auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { } + + /** + * @brief %auto_ptr assignment operator. + * @param __a Another %auto_ptr of the same type. + * + * This object now @e owns the object previously owned by @a __a, + * which has given up ownership. The object that this one @e + * used to own and track has been deleted. + */ + auto_ptr& + operator=(auto_ptr& __a) throw() + { + reset(__a.release()); + return *this; + } + + /** + * @brief %auto_ptr assignment operator. + * @param __a Another %auto_ptr of a different but related type. + * + * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type. + * + * This object now @e owns the object previously owned by @a __a, + * which has given up ownership. The object that this one @e + * used to own and track has been deleted. + */ + template + auto_ptr& + operator=(auto_ptr<_Tp1>& __a) throw() + { + reset(__a.release()); + return *this; + } + + /** + * When the %auto_ptr goes out of scope, the object it owns is + * deleted. If it no longer owns anything (i.e., @c get() is + * @c NULL), then this has no effect. + * + * The C++ standard says there is supposed to be an empty throw + * specification here, but omitting it is standard conforming. Its + * presence can be detected only if _Tp::~_Tp() throws, but this is + * prohibited. [17.4.3.6]/2 + */ + ~auto_ptr() { delete _M_ptr; } + + /** + * @brief Smart pointer dereferencing. + * + * If this %auto_ptr no longer owns anything, then this + * operation will crash. (For a smart pointer, no longer owns + * anything is the same as being a null pointer, and you know + * what happens when you dereference one of those...) + */ + element_type& + operator*() const throw() + { + __glibcxx_assert(_M_ptr != 0); + return *_M_ptr; + } + + /** + * @brief Smart pointer dereferencing. + * + * This returns the pointer itself, which the language then will + * automatically cause to be dereferenced. + */ + element_type* + operator->() const throw() + { + __glibcxx_assert(_M_ptr != 0); + return _M_ptr; + } + + /** + * @brief Bypassing the smart pointer. + * @return The raw pointer being managed. + * + * You can get a copy of the pointer that this object owns, for + * situations such as passing to a function which only accepts + * a raw pointer. + * + * @note This %auto_ptr still owns the memory. + */ + element_type* + get() const throw() { return _M_ptr; } + + /** + * @brief Bypassing the smart pointer. + * @return The raw pointer being managed. + * + * You can get a copy of the pointer that this object owns, for + * situations such as passing to a function which only accepts + * a raw pointer. + * + * @note This %auto_ptr no longer owns the memory. When this object + * goes out of scope, nothing will happen. + */ + element_type* + release() throw() + { + element_type* __tmp = _M_ptr; + _M_ptr = 0; + return __tmp; + } + + /** + * @brief Forcibly deletes the managed object. + * @param __p A pointer (defaults to NULL). + * + * This object now @e owns the object pointed to by @a __p. The + * previous object has been deleted. + */ + void + reset(element_type* __p = 0) throw() + { + if (__p != _M_ptr) + { + delete _M_ptr; + _M_ptr = __p; + } + } + + /** + * @brief Automatic conversions + * + * These operations are supposed to convert an %auto_ptr into and from + * an auto_ptr_ref automatically as needed. This would allow + * constructs such as + * @code + * auto_ptr func_returning_auto_ptr(.....); + * ... + * auto_ptr ptr = func_returning_auto_ptr(.....); + * @endcode + * + * But it doesn't work, and won't be fixed. For further details see + * http://cplusplus.github.io/LWG/lwg-closed.html#463 + */ + auto_ptr(auto_ptr_ref __ref) throw() + : _M_ptr(__ref._M_ptr) { } + + auto_ptr& + operator=(auto_ptr_ref __ref) throw() + { + if (__ref._M_ptr != this->get()) + { + delete _M_ptr; + _M_ptr = __ref._M_ptr; + } + return *this; + } + + template + operator auto_ptr_ref<_Tp1>() throw() + { return auto_ptr_ref<_Tp1>(this->release()); } + + template + operator auto_ptr<_Tp1>() throw() + { return auto_ptr<_Tp1>(this->release()); } + } _GLIBCXX11_DEPRECATED_SUGGEST("std::unique_ptr"); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 541. shared_ptr template assignment and void + template<> + class auto_ptr + { + public: + typedef void element_type; + } _GLIBCXX11_DEPRECATED; + +#if __cplusplus >= 201103L +#if _GLIBCXX_HOSTED + template<_Lock_policy _Lp> + template + inline + __shared_count<_Lp>::__shared_count(std::auto_ptr<_Tp>&& __r) + : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get())) + { __r.release(); } + + template + template + inline + __shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r) + : _M_ptr(__r.get()), _M_refcount() + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + static_assert( sizeof(_Tp1) > 0, "incomplete type" ); + _Tp1* __tmp = __r.get(); + _M_refcount = __shared_count<_Lp>(std::move(__r)); + _M_enable_shared_from_this_with(__tmp); + } + + template + template + inline + shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r) + : __shared_ptr<_Tp>(std::move(__r)) { } +#endif // HOSTED + + template + template + inline + unique_ptr<_Tp, _Dp>::unique_ptr(auto_ptr<_Up>&& __u) noexcept + : _M_t(__u.release(), deleter_type()) { } +#endif // C++11 + +#pragma GCC diagnostic pop + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _BACKWARD_AUTO_PTR_H */ diff --git a/template/sysroot/include/backward/binders.h b/template/sysroot/include/backward/binders.h new file mode 100644 index 0000000..ab670a8 --- /dev/null +++ b/template/sysroot/include/backward/binders.h @@ -0,0 +1,184 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file backward/binders.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _BACKWARD_BINDERS_H +#define _BACKWARD_BINDERS_H 1 + +// Suppress deprecated warning for this file. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.6 binders + /** @defgroup binders Binder Classes + * @ingroup functors + * + * Binders turn functions/functors with two arguments into functors + * with a single argument, storing an argument to be applied later. + * For example, a variable @c B of type @c binder1st is constructed + * from a functor @c f and an argument @c x. Later, B's @c + * operator() is called with a single argument @c y. The return + * value is the value of @c f(x,y). @c B can be @a called with + * various arguments (y1, y2, ...) and will in turn call @c + * f(x,y1), @c f(x,y2), ... + * + * The function @c bind1st is provided to save some typing. It takes the + * function and an argument as parameters, and returns an instance of + * @c binder1st. + * + * The type @c binder2nd and its creator function @c bind2nd do the same + * thing, but the stored argument is passed as the second parameter instead + * of the first, e.g., @c bind2nd(std::minus(),1.3) will create a + * functor whose @c operator() accepts a floating-point number, subtracts + * 1.3 from it, and returns the result. (If @c bind1st had been used, + * the functor would perform 1.3 - x instead. + * + * Creator-wrapper functions like @c bind1st are intended to be used in + * calling algorithms. Their return values will be temporary objects. + * (The goal is to not require you to type names like + * @c std::binder1st> for declaring a variable to hold the + * return value from @c bind1st(std::plus(),5). + * + * These become more useful when combined with the composition functions. + * + * These functions are deprecated in C++11 and can be replaced by + * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible, + * supporting functions with any number of arguments. Uses of @c bind1st + * can be replaced by @c std::bind(f, x, std::placeholders::_1) and + * @c bind2nd by @c std::bind(f, std::placeholders::_1, x). + * @{ + */ + /// One of the @link binders binder functors@endlink. + template + class binder1st + : public unary_function + { + protected: + _Operation op; + typename _Operation::first_argument_type value; + + public: + binder1st(const _Operation& __x, + const typename _Operation::first_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + } _GLIBCXX11_DEPRECATED_SUGGEST("std::bind"); + + /// One of the @link binders binder functors@endlink. + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::bind") + inline binder1st<_Operation> + bind1st(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::first_argument_type _Arg1_type; + return binder1st<_Operation>(__fn, _Arg1_type(__x)); + } + + /// One of the @link binders binder functors@endlink. + template + class binder2nd + : public unary_function + { + protected: + _Operation op; + typename _Operation::second_argument_type value; + + public: + binder2nd(const _Operation& __x, + const typename _Operation::second_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + } _GLIBCXX11_DEPRECATED_SUGGEST("std::bind"); + + /// One of the @link binders binder functors@endlink. + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::bind") + inline binder2nd<_Operation> + bind2nd(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::second_argument_type _Arg2_type; + return binder2nd<_Operation>(__fn, _Arg2_type(__x)); + } + /** @} */ + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop + +#endif /* _BACKWARD_BINDERS_H */ diff --git a/template/sysroot/include/bearssl.h b/template/sysroot/include/bearssl.h new file mode 100644 index 0000000..310edb2 --- /dev/null +++ b/template/sysroot/include/bearssl.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_H__ +#define BR_BEARSSL_H__ + +#include +#include + +/** \mainpage BearSSL API + * + * # API Layout + * + * The functions and structures defined by the BearSSL API are located + * in various header files: + * + * | Header file | Elements | + * | :-------------- | :------------------------------------------------ | + * | bearssl_hash.h | Hash functions | + * | bearssl_hmac.h | HMAC | + * | bearssl_kdf.h | Key Derivation Functions | + * | bearssl_rand.h | Pseudorandom byte generators | + * | bearssl_prf.h | PRF implementations (for SSL/TLS) | + * | bearssl_block.h | Symmetric encryption | + * | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) | + * | bearssl_rsa.h | RSA encryption and signatures | + * | bearssl_ec.h | Elliptic curves support (including ECDSA) | + * | bearssl_ssl.h | SSL/TLS engine interface | + * | bearssl_x509.h | X.509 certificate decoding and validation | + * | bearssl_pem.h | Base64/PEM decoding support functions | + * + * Applications using BearSSL are supposed to simply include `bearssl.h` + * as follows: + * + * #include + * + * The `bearssl.h` file itself includes all the other header files. It is + * possible to include specific header files, but it has no practical + * advantage for the application. The API is separated into separate + * header files only for documentation convenience. + * + * + * # Conventions + * + * ## MUST and SHALL + * + * In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology + * is used. Failure to meet requirements expressed with a "MUST" or + * "SHALL" implies undefined behaviour, which means that segmentation + * faults, buffer overflows, and other similar adverse events, may occur. + * + * In general, BearSSL is not very forgiving of programming errors, and + * does not include much failsafes or error reporting when the problem + * does not arise from external transient conditions, and can be fixed + * only in the application code. This is done so in order to make the + * total code footprint lighter. + * + * + * ## `NULL` values + * + * Function parameters with a pointer type shall not be `NULL` unless + * explicitly authorised by the documentation. As an exception, when + * the pointer aims at a sequence of bytes and is accompanied with + * a length parameter, and the length is zero (meaning that there is + * no byte at all to retrieve), then the pointer may be `NULL` even if + * not explicitly allowed. + * + * + * ## Memory Allocation + * + * BearSSL does not perform dynamic memory allocation. This implies that + * for any functionality that requires a non-transient state, the caller + * is responsible for allocating the relevant context structure. Such + * allocation can be done in any appropriate area, including static data + * segments, the heap, and the stack, provided that proper alignment is + * respected. The header files define these context structures + * (including size and contents), so the C compiler should handle + * alignment automatically. + * + * Since there is no dynamic resource allocation, there is also nothing to + * release. When the calling code is done with a BearSSL feature, it + * may simple release the context structures it allocated itself, with + * no "close function" to call. If the context structures were allocated + * on the stack (as local variables), then even that release operation is + * implicit. + * + * + * ## Structure Contents + * + * Except when explicitly indicated, structure contents are opaque: they + * are included in the header files so that calling code may know the + * structure sizes and alignment requirements, but callers SHALL NOT + * access individual fields directly. For fields that are supposed to + * be read from or written to, the API defines accessor functions (the + * simplest of these accessor functions are defined as `static inline` + * functions, and the C compiler will optimise them away). + * + * + * # API Usage + * + * BearSSL usage for running a SSL/TLS client or server is described + * on the [BearSSL Web site](https://www.bearssl.org/api1.html). The + * BearSSL source archive also comes with sample code. + */ + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_kdf.h" +#include "bearssl_rand.h" +#include "bearssl_prf.h" +#include "bearssl_block.h" +#include "bearssl_aead.h" +#include "bearssl_rsa.h" +#include "bearssl_ec.h" +#include "bearssl_ssl.h" +#include "bearssl_x509.h" +#include "bearssl_pem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Type for a configuration option. + * + * A "configuration option" is a value that is selected when the BearSSL + * library itself is compiled. Most options are boolean; their value is + * then either 1 (option is enabled) or 0 (option is disabled). Some + * values have other integer values. Option names correspond to macro + * names. Some of the options can be explicitly set in the internal + * `"config.h"` file. + */ +typedef struct { + /** \brief Configurable option name. */ + const char *name; + /** \brief Configurable option value. */ + long value; +} br_config_option; + +/** \brief Get configuration report. + * + * This function returns compiled configuration options, each as a + * 'long' value. Names match internal macro names, in particular those + * that can be set in the `"config.h"` inner file. For boolean options, + * the numerical value is 1 if enabled, 0 if disabled. For maximum + * key sizes, values are expressed in bits. + * + * The returned array is terminated by an entry whose `name` is `NULL`. + * + * \return the configuration report. + */ +const br_config_option *br_get_config(void); + +/* ======================================================================= */ + +/** \brief Version feature: support for time callback. */ +#define BR_FEATURE_X509_TIME_CALLBACK 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl.h b/template/sysroot/include/bearssl/bearssl.h new file mode 100644 index 0000000..310edb2 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_H__ +#define BR_BEARSSL_H__ + +#include +#include + +/** \mainpage BearSSL API + * + * # API Layout + * + * The functions and structures defined by the BearSSL API are located + * in various header files: + * + * | Header file | Elements | + * | :-------------- | :------------------------------------------------ | + * | bearssl_hash.h | Hash functions | + * | bearssl_hmac.h | HMAC | + * | bearssl_kdf.h | Key Derivation Functions | + * | bearssl_rand.h | Pseudorandom byte generators | + * | bearssl_prf.h | PRF implementations (for SSL/TLS) | + * | bearssl_block.h | Symmetric encryption | + * | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) | + * | bearssl_rsa.h | RSA encryption and signatures | + * | bearssl_ec.h | Elliptic curves support (including ECDSA) | + * | bearssl_ssl.h | SSL/TLS engine interface | + * | bearssl_x509.h | X.509 certificate decoding and validation | + * | bearssl_pem.h | Base64/PEM decoding support functions | + * + * Applications using BearSSL are supposed to simply include `bearssl.h` + * as follows: + * + * #include + * + * The `bearssl.h` file itself includes all the other header files. It is + * possible to include specific header files, but it has no practical + * advantage for the application. The API is separated into separate + * header files only for documentation convenience. + * + * + * # Conventions + * + * ## MUST and SHALL + * + * In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology + * is used. Failure to meet requirements expressed with a "MUST" or + * "SHALL" implies undefined behaviour, which means that segmentation + * faults, buffer overflows, and other similar adverse events, may occur. + * + * In general, BearSSL is not very forgiving of programming errors, and + * does not include much failsafes or error reporting when the problem + * does not arise from external transient conditions, and can be fixed + * only in the application code. This is done so in order to make the + * total code footprint lighter. + * + * + * ## `NULL` values + * + * Function parameters with a pointer type shall not be `NULL` unless + * explicitly authorised by the documentation. As an exception, when + * the pointer aims at a sequence of bytes and is accompanied with + * a length parameter, and the length is zero (meaning that there is + * no byte at all to retrieve), then the pointer may be `NULL` even if + * not explicitly allowed. + * + * + * ## Memory Allocation + * + * BearSSL does not perform dynamic memory allocation. This implies that + * for any functionality that requires a non-transient state, the caller + * is responsible for allocating the relevant context structure. Such + * allocation can be done in any appropriate area, including static data + * segments, the heap, and the stack, provided that proper alignment is + * respected. The header files define these context structures + * (including size and contents), so the C compiler should handle + * alignment automatically. + * + * Since there is no dynamic resource allocation, there is also nothing to + * release. When the calling code is done with a BearSSL feature, it + * may simple release the context structures it allocated itself, with + * no "close function" to call. If the context structures were allocated + * on the stack (as local variables), then even that release operation is + * implicit. + * + * + * ## Structure Contents + * + * Except when explicitly indicated, structure contents are opaque: they + * are included in the header files so that calling code may know the + * structure sizes and alignment requirements, but callers SHALL NOT + * access individual fields directly. For fields that are supposed to + * be read from or written to, the API defines accessor functions (the + * simplest of these accessor functions are defined as `static inline` + * functions, and the C compiler will optimise them away). + * + * + * # API Usage + * + * BearSSL usage for running a SSL/TLS client or server is described + * on the [BearSSL Web site](https://www.bearssl.org/api1.html). The + * BearSSL source archive also comes with sample code. + */ + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_kdf.h" +#include "bearssl_rand.h" +#include "bearssl_prf.h" +#include "bearssl_block.h" +#include "bearssl_aead.h" +#include "bearssl_rsa.h" +#include "bearssl_ec.h" +#include "bearssl_ssl.h" +#include "bearssl_x509.h" +#include "bearssl_pem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Type for a configuration option. + * + * A "configuration option" is a value that is selected when the BearSSL + * library itself is compiled. Most options are boolean; their value is + * then either 1 (option is enabled) or 0 (option is disabled). Some + * values have other integer values. Option names correspond to macro + * names. Some of the options can be explicitly set in the internal + * `"config.h"` file. + */ +typedef struct { + /** \brief Configurable option name. */ + const char *name; + /** \brief Configurable option value. */ + long value; +} br_config_option; + +/** \brief Get configuration report. + * + * This function returns compiled configuration options, each as a + * 'long' value. Names match internal macro names, in particular those + * that can be set in the `"config.h"` inner file. For boolean options, + * the numerical value is 1 if enabled, 0 if disabled. For maximum + * key sizes, values are expressed in bits. + * + * The returned array is terminated by an entry whose `name` is `NULL`. + * + * \return the configuration report. + */ +const br_config_option *br_get_config(void); + +/* ======================================================================= */ + +/** \brief Version feature: support for time callback. */ +#define BR_FEATURE_X509_TIME_CALLBACK 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_aead.h b/template/sysroot/include/bearssl/bearssl_aead.h new file mode 100644 index 0000000..8e35a1f --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_aead.h @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_AEAD_H__ +#define BR_BEARSSL_AEAD_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_aead.h + * + * # Authenticated Encryption with Additional Data + * + * This file documents the API for AEAD encryption. + * + * + * ## Procedural API + * + * An AEAD algorithm processes messages and provides confidentiality + * (encryption) and checked integrity (MAC). It uses the following + * parameters: + * + * - A symmetric key. Exact size depends on the AEAD algorithm. + * + * - A nonce (IV). Size depends on the AEAD algorithm; for most + * algorithms, it is crucial for security that any given nonce + * value is never used twice for the same key and distinct + * messages. + * + * - Data to encrypt and protect. + * + * - Additional authenticated data, which is covered by the MAC but + * otherwise left untouched (i.e. not encrypted). + * + * The AEAD algorithm encrypts the data, and produces an authentication + * tag. It is assumed that the encrypted data, the tag, the additional + * authenticated data and the nonce are sent to the receiver; the + * additional data and the nonce may be implicit (e.g. using elements of + * the underlying transport protocol, such as record sequence numbers). + * The receiver will recompute the tag value and compare it with the one + * received; if they match, then the data is correct, and can be + * decrypted and used; otherwise, at least one of the elements was + * altered in transit, normally leading to wholesale rejection of the + * complete message. + * + * For each AEAD algorithm, identified by a symbolic name (hereafter + * denoted as "`xxx`"), the following functions are defined: + * + * - `br_xxx_init()` + * + * Initialise the AEAD algorithm, on a provided context structure. + * Exact parameters depend on the algorithm, and may include + * pointers to extra implementations and context structures. The + * secret key is provided at this point, either directly or + * indirectly. + * + * - `br_xxx_reset()` + * + * Start a new AEAD computation. The nonce value is provided as + * parameter to this function. + * + * - `br_xxx_aad_inject()` + * + * Inject some additional authenticated data. Additional data may + * be provided in several chunks of arbitrary length. + * + * - `br_xxx_flip()` + * + * This function MUST be called after injecting all additional + * authenticated data, and before beginning to encrypt the plaintext + * (or decrypt the ciphertext). + * + * - `br_xxx_run()` + * + * Process some plaintext (to encrypt) or ciphertext (to decrypt). + * Encryption/decryption is done in place. Data may be provided in + * several chunks of arbitrary length. + * + * - `br_xxx_get_tag()` + * + * Compute the authentication tag. All message data (encrypted or + * decrypted) must have been injected at that point. Also, this + * call may modify internal context elements, so it may be called + * only once for a given AEAD computation. + * + * - `br_xxx_check_tag()` + * + * An alternative to `br_xxx_get_tag()`, meant to be used by the + * receiver: the authentication tag is internally recomputed, and + * compared with the one provided as parameter. + * + * This API makes the following assumptions on the AEAD algorithm: + * + * - Encryption does not expand the size of the ciphertext; there is + * no padding. This is true of most modern AEAD modes such as GCM. + * + * - The additional authenticated data must be processed first, + * before the encrypted/decrypted data. + * + * - Nonce, plaintext and additional authenticated data all consist + * in an integral number of bytes. There is no provision to use + * elements whose length in bits is not a multiple of 8. + * + * Each AEAD algorithm has its own requirements and limits on the sizes + * of additional data and plaintext. This API does not provide any + * way to report invalid usage; it is up to the caller to ensure that + * the provided key, nonce, and data elements all fit the algorithm's + * requirements. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `reset` + * + * Pointer to the reset function, that allows starting a new + * computation. + * + * - `aad_inject` + * + * Pointer to the additional authenticated data injection function. + * + * - `flip` + * + * Pointer to the function that transitions from additional data + * to main message data processing. + * + * - `get_tag` + * + * Pointer to the function that computes and returns the tag. + * + * - `check_tag` + * + * Pointer to the function that computes and verifies the tag against + * a received value. + * + * Note that there is no OOP method for context initialisation: the + * various AEAD algorithms have different requirements that would not + * map well to a single initialisation API. + * + * The OOP API is not provided for CCM, due to its specific requirements + * (length of plaintext must be known in advance). + */ + +/** + * \brief Class type of an AEAD algorithm. + */ +typedef struct br_aead_class_ br_aead_class; +struct br_aead_class_ { + + /** + * \brief Size (in bytes) of authentication tags created by + * this AEAD algorithm. + */ + size_t tag_size; + + /** + * \brief Reset an AEAD context. + * + * This function resets an already initialised AEAD context for + * a new computation run. Implementations and keys are + * conserved. This function can be called at any time; it + * cancels any ongoing AEAD computation that uses the provided + * context structure. + + * The provided IV is a _nonce_. Each AEAD algorithm has its + * own requirements on IV size and contents; for most of them, + * it is crucial to security that each nonce value is used + * only once for a given secret key. + * + * \param cc AEAD context structure. + * \param iv AEAD nonce to use. + * \param len AEAD nonce length (in bytes). + */ + void (*reset)(const br_aead_class **cc, const void *iv, size_t len); + + /** + * \brief Inject additional authenticated data. + * + * The provided data is injected into a running AEAD + * computation. Additional data must be injected _before_ the + * call to `flip()`. Additional data can be injected in several + * chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ + void (*aad_inject)(const br_aead_class **cc, + const void *data, size_t len); + + /** + * \brief Finish injection of additional authenticated data. + * + * This function MUST be called before beginning the actual + * encryption or decryption (with `run()`), even if no + * additional authenticated data was injected. No additional + * authenticated data may be injected after this function call. + * + * \param cc AEAD context structure. + */ + void (*flip)(const br_aead_class **cc); + + /** + * \brief Encrypt or decrypt some data. + * + * Data encryption or decryption can be done after `flip()` has + * been called on the context. If `encrypt` is non-zero, then + * the provided data shall be plaintext, and it is encrypted in + * place. Otherwise, the data shall be ciphertext, and it is + * decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ + void (*run)(const br_aead_class **cc, int encrypt, + void *data, size_t len); + + /** + * \brief Compute authentication tag. + * + * Compute the AEAD authentication tag. The tag length depends + * on the AEAD algorithm; it is written in the provided `tag` + * buffer. This call terminates the AEAD run: no data may be + * processed with that AEAD context afterwards, until `reset()` + * is called to initiate a new AEAD run. + * + * The tag value must normally be sent along with the encrypted + * data. When decrypting, the tag value must be recomputed and + * compared with the received tag: if the two tag values differ, + * then either the tag or the encrypted data was altered in + * transit. As an alternative to this function, the + * `check_tag()` function may be used to compute and check the + * tag value. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + */ + void (*get_tag)(const br_aead_class **cc, void *tag); + + /** + * \brief Compute and check authentication tag. + * + * This function is an alternative to `get_tag()`, and is + * normally used on the receiving end (i.e. when decrypting + * messages). The tag value is recomputed and compared with the + * provided tag value. If they match, 1 is returned; on + * mismatch, 0 is returned. A returned value of 0 means that the + * data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag)(const br_aead_class **cc, const void *tag); + + /** + * \brief Compute authentication tag (with truncation). + * + * This function is similar to `get_tag()`, except that the tag + * length is provided. Some AEAD algorithms allow several tag + * lengths, usually by truncating the normal tag. Shorter tags + * mechanically increase success probability of forgeries. + * The range of allowed tag lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + * \param len tag length (in bytes). + */ + void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len); + + /** + * \brief Compute and check authentication tag (with truncation). + * + * This function is similar to `check_tag()` except that it + * works over an explicit tag length. See `get_tag()` for a + * discussion of explicit tag lengths; the range of allowed tag + * lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag_trunc)(const br_aead_class **cc, + const void *tag, size_t len); +}; + +/** + * \brief Context structure for GCM. + * + * GCM is an AEAD mode that combines a block cipher in CTR mode with a + * MAC based on GHASH, to provide authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with GCM. + * + * - The nonce can have any length, from 0 up to 2^64-1 bits; however, + * 96-bit nonces (12 bytes) are recommended (nonces with a length + * distinct from 12 bytes are internally hashed, which risks reusing + * nonce value with a small but not always negligible probability). + * + * - Additional authenticated data may have length up to 2^64-1 bits. + * + * - Message length may range up to 2^39-256 bits at most. + * + * - The authentication tag has length 16 bytes. + * + * The GCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * GCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctr_class **bctx; + br_ghash gh; + unsigned char h[16]; + unsigned char j0_1[12]; + unsigned char buf[16]; + unsigned char y[16]; + uint32_t j0_2, jc; + uint64_t count_aad, count_ctr; +#endif +} br_gcm_context; + +/** + * \brief Initialize a GCM context. + * + * A block cipher implementation, with its initialised context structure, + * is provided. The block cipher MUST use 16-byte blocks in CTR mode, + * and its secret key MUST have been already set in the provided context. + * A GHASH implementation must also be provided. The parameters are linked + * in the GCM context. + * + * After this function has been called, the `br_gcm_reset()` function must + * be called, to provide the IV for GCM computation. + * + * \param ctx GCM context structure. + * \param bctx block cipher context (already initialised with secret key). + * \param gh GHASH implementation. + */ +void br_gcm_init(br_gcm_context *ctx, + const br_block_ctr_class **bctx, br_ghash gh); + +/** + * \brief Reset a GCM context. + * + * This function resets an already initialised GCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing GCM computation that + * uses the provided context structure. + * + * The provided IV is a _nonce_. It is critical to GCM security that IV + * values are not repeated for the same encryption key. IV can have + * arbitrary length (up to 2^64-1 bits), but the "normal" length is + * 96 bits (12 bytes). + * + * \param ctx GCM context structure. + * \param iv GCM nonce to use. + * \param len GCM nonce length (in bytes). + */ +void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len); + +/** + * \brief Inject additional authenticated data into GCM. + * + * The provided data is injected into a running GCM computation. Additional + * data must be injected _before_ the call to `br_gcm_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the maximum total size of additional authenticated data is 2^64-1 + * bits. + * + * \param ctx GCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into GCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_gcm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx GCM context structure. + */ +void br_gcm_flip(br_gcm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with GCM. + * + * Data encryption or decryption can be done after `br_gcm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. The maximum + * total length for data is 2^39-256 bits, i.e. about 65 gigabytes. + * + * \param ctx GCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute GCM authentication tag. + * + * Compute the GCM authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * GCM run: no data may be processed with that GCM context afterwards, + * until `br_gcm_reset()` is called to initiate a new GCM run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_gcm_get_tag(br_gcm_context *ctx, void *tag); + +/** + * \brief Compute and check GCM authentication tag. + * + * This function is an alternative to `br_gcm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag); + +/** + * \brief Compute GCM authentication tag (with truncation). + * + * This function is similar to `br_gcm_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the GCM run: no data may be processed with that GCM context + * afterwards, until `br_gcm_reset()` is called to initiate a new GCM + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check GCM authentication tag (with truncation). + * + * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for GCM. + */ +extern const br_aead_class br_gcm_vtable; + +/** + * \brief Context structure for EAX. + * + * EAX is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with EAX + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The nonce can have any length, as long as nonce values are + * not reused (thus, if nonces are randomly selected, the nonce + * size should be such that reuse probability is negligible). + * + * - Additional authenticated data length is unlimited. + * + * - Message length is unlimited. + * + * - The authentication tag has length 16 bytes. + * + * The EAX initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * EAX context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char L2[16]; + unsigned char L4[16]; + unsigned char nonce[16]; + unsigned char head[16]; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char buf[16]; + size_t ptr; +#endif +} br_eax_context; + +/** + * \brief EAX captured state. + * + * Some internal values computed by EAX may be captured at various + * points, and reused for another EAX run with the same secret key, + * for lower per-message overhead. Captured values do not depend on + * the nonce. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char st[3][16]; +#endif +} br_eax_state; + +/** + * \brief Initialize an EAX context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the EAX context. + * + * After this function has been called, the `br_eax_reset()` function must + * be called, to provide the nonce for EAX computation. + * + * \param ctx EAX context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Capture pre-AAD state. + * + * This function precomputes key-dependent data, and stores it in the + * provided `st` structure. This structure should then be used with + * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()` + * and then used with `br_eax_reset_post_aad()`. + * + * The EAX context structure is unmodified by this call. + * + * \param ctx EAX context structure. + * \param st recipient for captured state. + */ +void br_eax_capture(const br_eax_context *ctx, br_eax_state *st); + +/** + * \brief Reset an EAX context. + * + * This function resets an already initialised EAX context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing EAX computation that + * uses the provided context structure. + * + * It is critical to EAX security that nonce values are not repeated for + * the same encryption key. Nonces can have arbitrary length. If nonces + * are randomly generated, then a nonce length of at least 128 bits (16 + * bytes) is recommended, to make nonce reuse probability sufficiently + * low. + * + * \param ctx EAX context structure. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a pre-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * but not updated with `br_eax_get_aad_mac()`. + * + * After this function is called, additional authenticated data MUST + * be injected. At least one byte of additional authenticated data + * MUST be provided with `br_eax_aad_inject()`; computation result will + * be incorrect if `br_eax_flip()` is called right away. + * + * After injection of the AAD and call to `br_eax_flip()`, at least + * one message byte must be provided. Empty messages are not supported + * with this reset mode. + * + * \param ctx EAX context structure. + * \param st pre-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a post-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * and then updated with `br_eax_get_aad_mac()`. + * + * After this function is called, message data MUST be injected. The + * `br_eax_flip()` function MUST NOT be called. At least one byte of + * message data MUST be provided with `br_eax_run()`; empty messages + * are not supported with this reset mode. + * + * \param ctx EAX context structure. + * \param st post-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Inject additional authenticated data into EAX. + * + * The provided data is injected into a running EAX computation. Additional + * data must be injected _before_ the call to `br_eax_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the total amount of additional authenticated data is unlimited. + * + * \param ctx EAX context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into EAX. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_eax_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx EAX context structure. + */ +void br_eax_flip(br_eax_context *ctx); + +/** + * \brief Obtain a copy of the MAC on additional authenticated data. + * + * This function may be called only after `br_eax_flip()`; it copies the + * AAD-specific MAC value into the provided state. The MAC value depends + * on the secret key and the additional data itself, but not on the + * nonce. The updated state `st` is meant to be used as parameter for a + * further `br_eax_reset_post_aad()` call. + * + * \param ctx EAX context structure. + * \param st captured state to update. + */ +static inline void +br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st) +{ + memcpy(st->st[1], ctx->head, sizeof ctx->head); +} + +/** + * \brief Encrypt or decrypt some data with EAX. + * + * Data encryption or decryption can be done after `br_eax_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param ctx EAX context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute EAX authentication tag. + * + * Compute the EAX authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * EAX run: no data may be processed with that EAX context afterwards, + * until `br_eax_reset()` is called to initiate a new EAX run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_eax_get_tag(br_eax_context *ctx, void *tag); + +/** + * \brief Compute and check EAX authentication tag. + * + * This function is an alternative to `br_eax_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag); + +/** + * \brief Compute EAX authentication tag (with truncation). + * + * This function is similar to `br_eax_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the EAX run: no data may be processed with that EAX context + * afterwards, until `br_eax_reset()` is called to initiate a new EAX + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check EAX authentication tag (with truncation). + * + * This function is an alternative to `br_eax_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag_trunc(br_eax_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for EAX. + */ +extern const br_aead_class br_eax_vtable; + +/** + * \brief Context structure for CCM. + * + * CCM is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with CCM + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The authentication tag length, and plaintext length, MUST be + * known when starting processing data. Plaintext and ciphertext + * can still be provided by chunks, but the total size must match + * the value provided upon initialisation. + * + * - The nonce length is constrained between 7 and 13 bytes (inclusive). + * Furthermore, the plaintext length, when encoded, must fit over + * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then + * the plaintext length cannot exceed 65535 bytes. + * + * - Additional authenticated data length is practically unlimited + * (formal limit is at 2^64 bytes). + * + * - The authentication tag has length 4 to 16 bytes (even values only). + * + * The CCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * CCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char tagmask[16]; + unsigned char buf[16]; + size_t ptr; + size_t tag_len; +#endif +} br_ccm_context; + +/** + * \brief Initialize a CCM context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the CCM context. + * + * After this function has been called, the `br_ccm_reset()` function must + * be called, to provide the nonce for CCM computation. + * + * \param ctx CCM context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Reset a CCM context. + * + * This function resets an already initialised CCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing CCM computation that + * uses the provided context structure. + * + * The `aad_len` parameter contains the total length, in bytes, of the + * additional authenticated data. It may be zero. That length MUST be + * exact. + * + * The `data_len` parameter contains the total length, in bytes, of the + * data that will be injected (plaintext or ciphertext). That length MUST + * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)). + * + * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range + * (inclusive). + * + * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and + * be an even integer. Short tags mechanically allow for higher forgery + * probabilities; hence, tag sizes smaller than 12 bytes shall be used only + * with care. + * + * It is critical to CCM security that nonce values are not repeated for + * the same encryption key. Random generation of nonces is not generally + * recommended, due to the relatively small maximum nonce value. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the tag or nonce length is out of range, or if the + * plaintext/ciphertext length cannot be encoded with the specified + * nonce length. + * + * \param ctx CCM context structure. + * \param nonce CCM nonce to use. + * \param nonce_len CCM nonce length (in bytes, 7 to 13). + * \param aad_len additional authenticated data length (in bytes). + * \param data_len plaintext/ciphertext length (in bytes). + * \param tag_len tag length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, + uint64_t aad_len, uint64_t data_len, size_t tag_len); + +/** + * \brief Inject additional authenticated data into CCM. + * + * The provided data is injected into a running CCM computation. Additional + * data must be injected _before_ the call to `br_ccm_flip()`. + * Additional data can be injected in several chunks of arbitrary length, + * but the total amount MUST exactly match the value which was provided + * to `br_ccm_reset()`. + * + * \param ctx CCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into CCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_ccm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx CCM context structure. + */ +void br_ccm_flip(br_ccm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with CCM. + * + * Data encryption or decryption can be done after `br_ccm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length, provided + * that the total length exactly matches the length provided to the + * `br_ccm_reset()` call. + * + * \param ctx CCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute CCM authentication tag. + * + * Compute the CCM authentication tag. This call terminates the CCM + * run: all data must have been injected with `br_ccm_run()` (in zero, + * one or more successive calls). After this function has been called, + * no more data can br processed; a `br_ccm_reset()` call is required + * to start a new message. + * + * The tag length was provided upon context initialisation (last call + * to `br_ccm_reset()`); it is returned by this function. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_ccm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx CCM context structure. + * \param tag destination buffer for the tag (up to 16 bytes). + * \return the tag length (in bytes). + */ +size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag); + +/** + * \brief Compute and check CCM authentication tag. + * + * This function is an alternative to `br_ccm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx CCM context structure. + * \param tag tag value to compare with (up to 16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_block.h b/template/sysroot/include/bearssl/bearssl_block.h new file mode 100644 index 0000000..683a490 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_block.h @@ -0,0 +1,2618 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_BLOCK_H__ +#define BR_BEARSSL_BLOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_block.h + * + * # Block Ciphers and Symmetric Ciphers + * + * This file documents the API for block ciphers and other symmetric + * ciphers. + * + * + * ## Procedural API + * + * For a block cipher implementation, up to three separate sets of + * functions are provided, for CBC encryption, CBC decryption, and CTR + * encryption/decryption. Each set has its own context structure, + * initialised with the encryption key. + * + * For CBC encryption and decryption, the data to encrypt or decrypt is + * referenced as a sequence of blocks. The implementations assume that + * there is no partial block; no padding is applied or removed. The + * caller is responsible for handling any kind of padding. + * + * Function for CTR encryption are defined only for block ciphers with + * blocks of 16 bytes or more (i.e. AES, but not DES/3DES). + * + * Each implemented block cipher is identified by an "internal name" + * from which are derived the names of structures and functions that + * implement the cipher. For the block cipher of internal name "`xxx`", + * the following are defined: + * + * - `br_xxx_BLOCK_SIZE` + * + * A macro that evaluates to the block size (in bytes) of the + * cipher. For all implemented block ciphers, this value is a + * power of two. + * + * - `br_xxx_cbcenc_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC encryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC encryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)` + * + * Perform CBC encryption of `len` bytes, in place. The encrypted data + * replaces the cleartext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last encrypted block. + * + * - `br_xxx_cbcdec_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC decryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC decryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)` + * + * Perform CBC decryption of `len` bytes, in place. The decrypted data + * replaces the ciphertext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last _encrypted_ block. + * + * - `br_xxx_ctr_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CTR encryption and + * decryption. The structure first field is called `vtable` and + * points to the appropriate OOP structure. + * + * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CTR encryption and decryption + * are computed and written in the provided context structure. The + * key length MUST be adequate for the implemented block cipher. This + * function also sets the `vtable` field. + * + * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`) + * + * Perform CTR encryption/decryption of some data. Processing is done + * "in place" (the output data replaces the input data). This function + * implements the "standard incrementing function" from NIST SP800-38A, + * annex B: the IV length shall be 4 bytes less than the block size + * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting + * with `cc`. The data length (`len`) is not necessarily a multiple of + * the block size. The new counter value is returned, which supports + * chunked processing, provided that each chunk length (except possibly + * the last one) is a multiple of the block size. + * + * - `br_xxx_ctrcbc_keys` + * + * Context structure that contains the subkeys resulting from the + * key expansion. These subkeys are appropriate for doing combined + * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX + * authenticated encryption modes. The structure first field is + * called `vtable` and points to the appropriate OOP structure. + * + * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for combined CTR + * encryption/decryption and CBC-MAC are computed and written in the + * provided context structure. The key length MUST be adequate for + * the implemented block cipher. This function also sets the + * `vtable` field. + * + * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR encryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR encryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (output of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR decryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR decryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (input of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)` + * + * Perform CTR encryption or decryption of the provided data. The + * data is processed "in place" (the output data replaces the input + * data). A full block-sized counter is applied (i.e. for 128-bit + * blocks, the counter is incremented as a 128-bit value). The 'ctr' + * array contains the initial value for the counter (used in the + * first block), and it is updated with the new value after data + * processing. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)` + * + * Compute CBC-MAC over the provided data. The IV for CBC-MAC is + * provided as 'cbcmac'; the output is written over the same array. + * The data itself is untouched. The data length MUST be a multiple + * of the block size. + * + * + * It shall be noted that the key expansion functions return `void`. If + * the provided key length is not allowed, then there will be no error + * reporting; implementations need not validate the key length, thus an + * invalid key length may result in undefined behaviour (e.g. buffer + * overflow). + * + * Subkey structures contain no interior pointer, and no external + * resources are allocated upon key expansion. They can thus be + * discarded without any explicit deallocation. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `run` + * + * Pointer to the encryption/decryption function. + * + * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly + * different structure: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `encrypt` + * + * Pointer to the CTR encryption + CBC-MAC function. + * + * - `decrypt` + * + * Pointer to the CTR decryption + CBC-MAC function. + * + * - `ctr` + * + * Pointer to the CTR encryption/decryption function. + * + * - `mac` + * + * Pointer to the CBC-MAC function. + * + * For block cipher "`xxx`", static, constant instances of these + * structures are defined, under the names: + * + * - `br_xxx_cbcenc_vtable` + * - `br_xxx_cbcdec_vtable` + * - `br_xxx_ctr_vtable` + * - `br_xxx_ctrcbc_vtable` + * + * + * ## Implemented Block Ciphers + * + * Provided implementations are: + * + * | Name | Function | Block Size (bytes) | Key lengths (bytes) | + * | :-------- | :------- | :----------------: | :-----------------: | + * | aes_big | AES | 16 | 16, 24 and 32 | + * | aes_small | AES | 16 | 16, 24 and 32 | + * | aes_ct | AES | 16 | 16, 24 and 32 | + * | aes_ct64 | AES | 16 | 16, 24 and 32 | + * | aes_x86ni | AES | 16 | 16, 24 and 32 | + * | aes_pwr8 | AES | 16 | 16, 24 and 32 | + * | des_ct | DES/3DES | 8 | 8, 16 and 24 | + * | des_tab | DES/3DES | 8 | 8, 16 and 24 | + * + * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8, + * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so + * the _effective_ key lengths, from a security point of view, are 56, + * 112 and 168 bits, respectively. + * + * `aes_big` is a "classical" AES implementation, using tables. It + * is fast but not constant-time, since it makes data-dependent array + * accesses. + * + * `aes_small` is an AES implementation optimized for code size. It + * is substantially slower than `aes_big`; it is not constant-time + * either. + * + * `aes_ct` is a constant-time implementation of AES; its code is about + * as big as that of `aes_big`, while its performance is comparable to + * that of `aes_small`. However, it is constant-time. This + * implementation should thus be considered to be the "default" AES in + * BearSSL, to be used unless the operational context guarantees that a + * non-constant-time implementation is safe, or an architecture-specific + * constant-time implementation can be used (e.g. using dedicated + * hardware opcodes). + * + * `aes_ct64` is another constant-time implementation of AES. It is + * similar to `aes_ct` but uses 64-bit values. On 32-bit machines, + * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has + * a larger footprint; however, on 64-bit architectures, `aes_ct64` + * is typically twice faster than `aes_ct` for modes that allow parallel + * operations (i.e. CTR, and CBC decryption, but not CBC encryption). + * + * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It + * uses the AES-NI opcodes when available. + * + * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and + * 64-bit, both little-endian and big-endian). It uses the AES opcodes + * present in POWER8 and later. + * + * `des_tab` is a classic, table-based implementation of DES/3DES. It + * is not constant-time. + * + * `des_ct` is an constant-time implementation of DES/3DES. It is + * substantially slower than `des_tab`. + * + * ## ChaCha20 and Poly1305 + * + * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They + * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539). + * + * Two function pointer types are defined: + * + * - `br_chacha20_run` describes a function that implements ChaCha20 + * only. + * + * - `br_poly1305_run` describes an implementation of Poly1305, + * in the AEAD combination with ChaCha20 specified in RFC 7539 + * (the ChaCha20 implementation is provided as a function pointer). + * + * `chacha20_ct` is a straightforward implementation of ChaCha20 in + * plain C; it is constant-time, small, and reasonably fast. + * + * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that + * support these opcodes). It is faster than `chacha20_ct`. + * + * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD + * construction, where the Poly1305 part is performed with mixed 32-bit + * multiplications (operands are 32-bit, result is 64-bit). + * + * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit + * multiplications (32-bit operands, 32-bit result). It is slower than + * `poly1305_ctmul`, except on some specific architectures such as + * the ARM Cortex M0+. + * + * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit + * multiplications (operands are 64-bit, result is 128-bit) on 64-bit + * platforms that support such operations. + * + * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15" + * big integer implementation. It is meant mostly for testing purposes, + * although it can help with saving a few hundred bytes of code footprint + * on systems where code size is scarce. + */ + +/** + * \brief Class type for CBC encryption implementations. + * + * A `br_block_cbcenc_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for encrypting data. + */ +typedef struct br_block_cbcenc_class_ br_block_cbcenc_class; +struct br_block_cbcenc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcenc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC encryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is encrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC encryption (updated). + * \param data data to encrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcenc_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CBC decryption implementations. + * + * A `br_block_cbcdec_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for decrypting data. + */ +typedef struct br_block_cbcdec_class_ br_block_cbcdec_class; +struct br_block_cbcdec_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcdec_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC decryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is decrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC decryption (updated). + * \param data data to decrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcdec_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CTR encryption/decryption implementations. + * + * A `br_block_ctr_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data. + */ +typedef struct br_block_ctr_class_ br_block_ctr_class; +struct br_block_ctr_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctr_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption or decryption. + * + * The `iv` parameter points to the IV for this run; its + * length is exactly 4 bytes less than the block size (e.g. + * 12 bytes for AES/CTR). The IV is combined with a 32-bit + * block counter to produce the block value which is processed + * with the block cipher. + * + * The data to encrypt or decrypt is updated "in place". Its + * length (`len` bytes) is not required to be a multiple of + * the block size; if the final block is partial, then the + * corresponding key stream bits are dropped. + * + * The resulting counter value is returned. + * + * \param ctx context structure (already initialised). + * \param iv IV for CTR encryption/decryption. + * \param cc initial value for the block counter. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \return the new block counter value. + */ + uint32_t (*run)(const br_block_ctr_class *const *ctx, + const void *iv, uint32_t cc, void *data, size_t len); +}; + +/** + * \brief Class type for combined CTR and CBC-MAC implementations. + * + * A `br_block_ctrcbc_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data, along with CBC-MAC. + */ +typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class; +struct br_block_ctrcbc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctrcbc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as encryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (output of CTR + * encryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to encrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to encrypt. + * \param len data length (in bytes). + */ + void (*encrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR decryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*decrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR encryption/decryption only. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*ctr)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *data, size_t len); + + /** + * \brief Run the CBC-MAC only. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data is unmodified. Its length (`len` bytes) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*mac)(const br_block_ctrcbc_class *const *ctx, + void *cbcmac, const void *data, size_t len); +}; + +/* + * Traditional, table-based AES implementation. It is fast, but uses + * internal tables (in particular a 1 kB table for encryption, another + * 1 kB table for decryption, and a 256-byte table for key schedule), + * and it is not constant-time. In contexts where cache-timing attacks + * apply, this implementation may leak the secret key. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_big_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_big` implementation). + */ +extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_big` implementation). + */ +extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_big` implementation). + */ +extern const br_block_ctr_class br_aes_big_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_big` implementation). + */ +extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to encrypt or decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation optimized for size. It is slower than the + * traditional table-based AES implementation, but requires much less + * code. It still uses data-dependent table accesses (albeit within a + * much smaller 256-byte table), which makes it conceptually vulnerable + * to cache-timing attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_small_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_small` implementation). + */ +extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_small` implementation). + */ +extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_small` implementation). + */ +extern const br_block_ctr_class br_aes_small_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_small` implementation). + */ +extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * Constant-time AES implementation. Its size is similar to that of + * 'aes_big', and its performance is similar to that of 'aes_small' (faster + * decryption, slower encryption). However, it is constant-time, i.e. + * immune to cache-timing and similar attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct` implementation). + */ +extern const br_block_ctr_class br_aes_ct_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * 64-bit constant-time AES implementation. It is similar to 'aes_ct' + * but uses 64-bit registers, making it about twice faster than 'aes_ct' + * on 64-bit platforms, while remaining constant-time and with a similar + * code size. (The doubling in performance is only for CBC decryption + * and CTR mode; CBC encryption is non-parallel and cannot benefit from + * the larger registers.) + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct64_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct64` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct64` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct64` implementation). + */ +extern const br_block_ctr_class br_aes_ct64_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct64` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation using AES-NI opcodes (x86 platform). + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_x86ni_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void); + +/* + * AES implementation using POWER8 opcodes. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_pwr8_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_pwr8_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that + * implementation was compiled in the library _and_ the POWER8 crypto + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void); + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all AES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_aes_big_cbcenc_keys c_big; + br_aes_small_cbcenc_keys c_small; + br_aes_ct_cbcenc_keys c_ct; + br_aes_ct64_cbcenc_keys c_ct64; + br_aes_x86ni_cbcenc_keys c_x86ni; + br_aes_pwr8_cbcenc_keys c_pwr8; +} br_aes_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all AES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_aes_big_cbcdec_keys c_big; + br_aes_small_cbcdec_keys c_small; + br_aes_ct_cbcdec_keys c_ct; + br_aes_ct64_cbcdec_keys c_ct64; + br_aes_x86ni_cbcdec_keys c_x86ni; + br_aes_pwr8_cbcdec_keys c_pwr8; +} br_aes_gen_cbcdec_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption and decryption) for all AES implementations. + */ +typedef union { + const br_block_ctr_class *vtable; + br_aes_big_ctr_keys c_big; + br_aes_small_ctr_keys c_small; + br_aes_ct_ctr_keys c_ct; + br_aes_ct64_ctr_keys c_ct64; + br_aes_x86ni_ctr_keys c_x86ni; + br_aes_pwr8_ctr_keys c_pwr8; +} br_aes_gen_ctr_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations. + */ +typedef union { + const br_block_ctrcbc_class *vtable; + br_aes_big_ctrcbc_keys c_big; + br_aes_small_ctrcbc_keys c_small; + br_aes_ct_ctrcbc_keys c_ct; + br_aes_ct64_ctrcbc_keys c_ct64; + br_aes_x86ni_ctrcbc_keys c_x86ni; + br_aes_pwr8_ctrcbc_keys c_pwr8; +} br_aes_gen_ctrcbc_keys; + +/* + * Traditional, table-based implementation for DES/3DES. Since tables are + * used, cache-timing attacks are conceptually possible. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_tab_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_tab` implementation). + */ +extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_tab` implementation). + */ +extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * Constant-time implementation for DES/3DES. It is substantially slower + * (by a factor of about 4x), but also immune to cache-timing attacks. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_ct_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_ct` implementation). + */ +extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_ct` implementation). + */ +extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * These structures are large enough to accommodate subkeys for all + * DES/3DES implementations. + */ + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all DES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_des_tab_cbcenc_keys tab; + br_des_ct_cbcenc_keys ct; +} br_des_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all DES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_des_tab_cbcdec_keys c_tab; + br_des_ct_cbcdec_keys c_ct; +} br_des_gen_cbcdec_keys; + +/** + * \brief Type for a ChaCha20 implementation. + * + * An implementation follows the description in RFC 7539: + * + * - Key is 256 bits (`key` points to exactly 32 bytes). + * + * - IV is 96 bits (`iv` points to exactly 12 bytes). + * + * - Block counter is over 32 bits and starts at value `cc`; the + * resulting value is returned. + * + * Data (pointed to by `data`, of length `len`) is encrypted/decrypted + * in place. If `len` is not a multiple of 64, then the excess bytes from + * the last block processing are dropped (therefore, "chunked" processing + * works only as long as each non-final chunk has a length multiple of 64). + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +typedef uint32_t (*br_chacha20_run)(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (straightforward C code, constant-time). + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_ct_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (SSE2 code, constant-time). + * + * This implementation is available only on x86 platforms, depending on + * compiler support. Moreover, in 32-bit mode, it might not actually run, + * if the underlying hardware does not implement the SSE2 opcode (in + * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled + * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain + * a pointer to that function. + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_sse2_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief Obtain the `sse2` ChaCha20 implementation, if available. + * + * This function returns a pointer to `br_chacha20_sse2_run`, if + * that implementation was compiled in the library _and_ the SSE2 + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `0`. + * + * \return the `sse2` ChaCha20 implementation, or `0`. + */ +br_chacha20_run br_chacha20_sse2_get(void); + +/** + * \brief Type for a ChaCha20+Poly1305 AEAD implementation. + * + * The provided data is encrypted or decrypted with ChaCha20. The + * authentication tag is computed on the concatenation of the + * additional data and the ciphertext, with the padding and lengths + * as described in RFC 7539 (section 2.8). + * + * After decryption, the caller is responsible for checking that the + * computed tag matches the expected value. + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +typedef void (*br_poly1305_run)(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul32_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (i15). + * + * This implementation relies on the generic big integer code "i15" + * (which uses pure 32-bit multiplications). As such, it may save a + * little code footprint in a context where "i15" is already included + * (e.g. for elliptic curves or for RSA); however, it is also + * substantially slower than the ctmul and ctmul32 implementations. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_i15_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq). + * + * This implementation uses 64-bit multiplications (result over 128 bits). + * It is available only on platforms that offer such a primitive (in + * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to + * dynamically obtain a pointer to that function, or 0 if not supported. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmulq_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available. + * + * This function returns a pointer to the `br_poly1305_ctmulq_run()` + * function if supported on the current platform; otherwise, it returns 0. + * + * \return the ctmulq ChaCha20+Poly1305 implementation, or 0. + */ +br_poly1305_run br_poly1305_ctmulq_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_ec.h b/template/sysroot/include/bearssl/bearssl_ec.h new file mode 100644 index 0000000..acd3a2b --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_ec.h @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_EC_H__ +#define BR_BEARSSL_EC_H__ + +#include +#include + +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ec.h + * + * # Elliptic Curves + * + * This file documents the EC implementations provided with BearSSL, and + * ECDSA. + * + * ## Elliptic Curve API + * + * Only "named curves" are supported. Each EC implementation supports + * one or several named curves, identified by symbolic identifiers. + * These identifiers are small integers, that correspond to the values + * registered by the + * [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8). + * + * Since all currently defined elliptic curve identifiers are in the 0..31 + * range, it is convenient to encode support of some curves in a 32-bit + * word, such that bit x corresponds to curve of identifier x. + * + * An EC implementation is incarnated by a `br_ec_impl` instance, that + * offers the following fields: + * + * - `supported_curves` + * + * A 32-bit word that documents the identifiers of the curves supported + * by this implementation. + * + * - `generator()` + * + * Callback method that returns a pointer to the conventional generator + * point for that curve. + * + * - `order()` + * + * Callback method that returns a pointer to the subgroup order for + * that curve. That value uses unsigned big-endian encoding. + * + * - `xoff()` + * + * Callback method that returns the offset and length of the X + * coordinate in an encoded point. + * + * - `mul()` + * + * Multiply a curve point with an integer. + * + * - `mulgen()` + * + * Multiply the curve generator with an integer. This may be faster + * than the generic `mul()`. + * + * - `muladd()` + * + * Multiply two curve points by two integers, and return the sum of + * the two products. + * + * All curve points are represented in uncompressed format. The `mul()` + * and `muladd()` methods take care to validate that the provided points + * are really part of the relevant curve subgroup. + * + * For all point multiplication functions, the following holds: + * + * - Functions validate that the provided points are valid members + * of the relevant curve subgroup. An error is reported if that is + * not the case. + * + * - Processing is constant-time, even if the point operands are not + * valid. This holds for both the source and resulting points, and + * the multipliers (integers). Only the byte length of the provided + * multiplier arrays (not their actual value length in bits) may + * leak through timing-based side channels. + * + * - The multipliers (integers) MUST be lower than the subgroup order. + * If this property is not met, then the result is indeterminate, + * but an error value is not necessarily returned. + * + * + * ## ECDSA + * + * ECDSA signatures have two standard formats, called "raw" and "asn1". + * Internally, such a signature is a pair of modular integers `(r,s)`. + * The "raw" format is the concatenation of the unsigned big-endian + * encodings of these two integers, possibly left-padded with zeros so + * that they have the same encoded length. The "asn1" format is the + * DER encoding of an ASN.1 structure that contains the two integer + * values: + * + * ECDSASignature ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * In general, in all of X.509 and SSL/TLS, the "asn1" format is used. + * BearSSL offers ECDSA implementations for both formats; conversion + * functions between the two formats are also provided. Conversion of a + * "raw" format signature into "asn1" may enlarge a signature by no more + * than 9 bytes for all supported curves; conversely, conversion of an + * "asn1" signature to "raw" may expand the signature but the "raw" + * length will never be more than twice the length of the "asn1" length + * (and usually it will be shorter). + * + * Note that for a given signature, the "raw" format is not fully + * deterministic, in that it does not enforce a minimal common length. + */ + +/* + * Standard curve ID. These ID are equal to the assigned numerical + * identifiers assigned to these curves for TLS: + * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + */ + +/** \brief Identifier for named curve sect163k1. */ +#define BR_EC_sect163k1 1 + +/** \brief Identifier for named curve sect163r1. */ +#define BR_EC_sect163r1 2 + +/** \brief Identifier for named curve sect163r2. */ +#define BR_EC_sect163r2 3 + +/** \brief Identifier for named curve sect193r1. */ +#define BR_EC_sect193r1 4 + +/** \brief Identifier for named curve sect193r2. */ +#define BR_EC_sect193r2 5 + +/** \brief Identifier for named curve sect233k1. */ +#define BR_EC_sect233k1 6 + +/** \brief Identifier for named curve sect233r1. */ +#define BR_EC_sect233r1 7 + +/** \brief Identifier for named curve sect239k1. */ +#define BR_EC_sect239k1 8 + +/** \brief Identifier for named curve sect283k1. */ +#define BR_EC_sect283k1 9 + +/** \brief Identifier for named curve sect283r1. */ +#define BR_EC_sect283r1 10 + +/** \brief Identifier for named curve sect409k1. */ +#define BR_EC_sect409k1 11 + +/** \brief Identifier for named curve sect409r1. */ +#define BR_EC_sect409r1 12 + +/** \brief Identifier for named curve sect571k1. */ +#define BR_EC_sect571k1 13 + +/** \brief Identifier for named curve sect571r1. */ +#define BR_EC_sect571r1 14 + +/** \brief Identifier for named curve secp160k1. */ +#define BR_EC_secp160k1 15 + +/** \brief Identifier for named curve secp160r1. */ +#define BR_EC_secp160r1 16 + +/** \brief Identifier for named curve secp160r2. */ +#define BR_EC_secp160r2 17 + +/** \brief Identifier for named curve secp192k1. */ +#define BR_EC_secp192k1 18 + +/** \brief Identifier for named curve secp192r1. */ +#define BR_EC_secp192r1 19 + +/** \brief Identifier for named curve secp224k1. */ +#define BR_EC_secp224k1 20 + +/** \brief Identifier for named curve secp224r1. */ +#define BR_EC_secp224r1 21 + +/** \brief Identifier for named curve secp256k1. */ +#define BR_EC_secp256k1 22 + +/** \brief Identifier for named curve secp256r1. */ +#define BR_EC_secp256r1 23 + +/** \brief Identifier for named curve secp384r1. */ +#define BR_EC_secp384r1 24 + +/** \brief Identifier for named curve secp521r1. */ +#define BR_EC_secp521r1 25 + +/** \brief Identifier for named curve brainpoolP256r1. */ +#define BR_EC_brainpoolP256r1 26 + +/** \brief Identifier for named curve brainpoolP384r1. */ +#define BR_EC_brainpoolP384r1 27 + +/** \brief Identifier for named curve brainpoolP512r1. */ +#define BR_EC_brainpoolP512r1 28 + +/** \brief Identifier for named curve Curve25519. */ +#define BR_EC_curve25519 29 + +/** \brief Identifier for named curve Curve448. */ +#define BR_EC_curve448 30 + +/** + * \brief Structure for an EC public key. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Public curve point (uncompressed format). */ + unsigned char *q; + /** \brief Length of public curve point (in bytes). */ + size_t qlen; +} br_ec_public_key; + +/** + * \brief Structure for an EC private key. + * + * The private key is an integer modulo the curve subgroup order. The + * encoding below tolerates extra leading zeros. In general, it is + * recommended that the private key has the same length as the curve + * subgroup order. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Private key (integer, unsigned big-endian encoding). */ + unsigned char *x; + /** \brief Private key length (in bytes). */ + size_t xlen; +} br_ec_private_key; + +/** + * \brief Type for an EC implementation. + */ +typedef struct { + /** + * \brief Supported curves. + * + * This word is a bitfield: bit `x` is set if the curve of ID `x` + * is supported. E.g. an implementation supporting both NIST P-256 + * (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have + * value `0x01800000` in this field. + */ + uint32_t supported_curves; + + /** + * \brief Get the conventional generator. + * + * This function returns the conventional generator (encoded + * curve point) for the specified curve. This function MUST NOT + * be called if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded generator length (in bytes). + * \return the encoded generator. + */ + const unsigned char *(*generator)(int curve, size_t *len); + + /** + * \brief Get the subgroup order. + * + * This function returns the order of the subgroup generated by + * the conventional generator, for the specified curve. Unsigned + * big-endian encoding is used. This function MUST NOT be called + * if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded order length (in bytes). + * \return the encoded order. + */ + const unsigned char *(*order)(int curve, size_t *len); + + /** + * \brief Get the offset and length for the X coordinate. + * + * This function returns the offset and length (in bytes) of + * the X coordinate in an encoded non-zero point. + * + * \param curve curve identifier. + * \param len receiver for the X coordinate length (in bytes). + * \return the offset for the X coordinate (in bytes). + */ + size_t (*xoff)(int curve, size_t *len); + + /** + * \brief Multiply a curve point by an integer. + * + * The source point is provided in array `G` (of size `Glen` bytes); + * the multiplication result is written over it. The multiplier + * `x` (of size `xlen` bytes) uses unsigned big-endian encoding. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source point must be a valid point on the relevant curve + * subgroup (and not the "point at infinity" either). If this is + * not the case, then this function returns an error (0). + * + * - The multiplier integer MUST be non-zero and less than the + * curve subgroup order. If this property does not hold, then + * the result is indeterminate and an error code is not + * guaranteed. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `G` are indeterminate. + * + * \param G point to multiply. + * \param Glen length of the encoded point (in bytes). + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*mul)(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply the generator by an integer. + * + * The multiplier MUST be non-zero and less than the curve + * subgroup order. Results are indeterminate if this property + * does not hold. + * + * \param R output buffer for the point. + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return encoded result point length (in bytes). + */ + size_t (*mulgen)(unsigned char *R, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply two points by two integers and add the + * results. + * + * The point `x*A + y*B` is computed and written back in the `A` + * array. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source points (`A` and `B`) must be valid points on + * the relevant curve subgroup (and not the "point at + * infinity" either). If this is not the case, then this + * function returns an error (0). + * + * - If the `B` pointer is `NULL`, then the conventional + * subgroup generator is used. With some implementations, + * this may be faster than providing a pointer to the + * generator. + * + * - The multiplier integers (`x` and `y`) MUST be non-zero + * and less than the curve subgroup order. If either integer + * is zero, then an error is reported, but if one of them is + * not lower than the subgroup order, then the result is + * indeterminate and an error code is not guaranteed. + * + * - If the final result is the point at infinity, then an + * error is returned. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `A` are indeterminate. + * + * \param A first point to multiply. + * \param B second point to multiply (`NULL` for the generator). + * \param len common length of the encoded points (in bytes). + * \param x multiplier for `A` (unsigned big-endian). + * \param xlen length of multiplier for `A` (in bytes). + * \param y multiplier for `A` (unsigned big-endian). + * \param ylen length of multiplier for `A` (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve); +} br_ec_impl; + +/** + * \brief EC implementation "i31". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 31-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i31; + +/** + * \brief EC implementation "i15". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 15-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i15; + +/** + * \brief EC implementation "m15" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), with optional Karatsuba decomposition, and fast + * modular reduction thanks to the field modulus special format. Only + * 32-bit multiplications are used (with 32-bit results, not 64-bit). + */ +extern const br_ec_impl br_ec_p256_m15; + +/** + * \brief EC implementation "m31" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), relying on multiplications of 31-bit values + * (MUL31). + */ +extern const br_ec_impl br_ec_p256_m31; + +/** + * \brief EC implementation "m62" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m62; + +/** + * \brief Get the "m62" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m64; + +/** + * \brief Get the "m64" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m64_get(void); + +/** + * \brief EC implementation "i15" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 15-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i15; + +/** + * \brief EC implementation "i31" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 31-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i31; + +/** + * \brief EC implementation "m15" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 15 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m15; + +/** + * \brief EC implementation "m31" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 31 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m31; + +/** + * \brief EC implementation "m62" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 62 bits, with a 124-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m62; + +/** + * \brief Get the "m62" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m64; + +/** + * \brief Get the "m64" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m64_get(void); + +/** + * \brief Aggregate EC implementation "m15". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m15` for Curve25519 + * - `br_ec_p256_m15` for NIST P-256 + * - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m15; + +/** + * \brief Aggregate EC implementation "m31". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m31` for Curve25519 + * - `br_ec_p256_m31` for NIST P-256 + * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m31; + +/** + * \brief Get the "default" EC implementation for the current system. + * + * This returns a pointer to the preferred implementation on the + * current system. + * + * \return the default EC implementation. + */ +const br_ec_impl *br_ec_get_default(void); + +/** + * \brief Convert a signature from "raw" to "asn1". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but by no more than 9 bytes at + * most. On error, 0 is returned (error conditions include an odd raw + * signature length, or an oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len); + +/** + * \brief Convert a signature from "asn1" to "raw". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but the new signature length + * will be less than twice the source length at most. On error, 0 is + * returned (error conditions include an invalid ASN.1 structure or an + * oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len); + +/** + * \brief Type for an ECDSA signer function. + * + * A pointer to the EC implementation is provided. The hash value is + * assumed to have the length inferred from the designated hash function + * class. + * + * Signature is written in the buffer pointed to by `sig`, and the length + * (in bytes) is returned. On error, nothing is written in the buffer, + * and 0 is returned. This function returns 0 if the specified curve is + * not supported by the provided EC implementation. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation; maximum length is predictable from the implemented + * curve: + * + * | curve | raw | asn1 | + * | :--------- | --: | ---: | + * | NIST P-256 | 64 | 72 | + * | NIST P-384 | 96 | 104 | + * | NIST P-521 | 132 | 139 | + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief Type for an ECDSA signature verification function. + * + * A pointer to the EC implementation is provided. The hashed value, + * computed over the purportedly signed data, is also provided with + * its length. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation. + * + * Returned value is 1 on success (valid signature), 0 on error. This + * function returns 0 if the specified curve is not supported by the + * provided EC implementation. + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i31" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i15" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief Get "default" ECDSA implementation (signer, asn1 format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (signer, raw format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, asn1 format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, raw format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); + +/** + * \brief Maximum size for EC private key element buffer. + * + * This is the largest number of bytes that `br_ec_keygen()` may need or + * ever return. + */ +#define BR_EC_KBUF_PRIV_MAX_SIZE 72 + +/** + * \brief Maximum size for EC public key element buffer. + * + * This is the largest number of bytes that `br_ec_compute_public()` may + * need or ever return. + */ +#define BR_EC_KBUF_PUB_MAX_SIZE 145 + +/** + * \brief Generate a new EC private key. + * + * If the specified `curve` is not supported by the elliptic curve + * implementation (`impl`), then this function returns zero. + * + * The `sk` structure fields are set to the new private key data. In + * particular, `sk.x` is made to point to the provided key buffer (`kbuf`), + * in which the actual private key data is written. That buffer is assumed + * to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum + * size for all supported curves. + * + * The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then + * the private key is not actually generated, and `sk` may also be `NULL`; + * the minimum length for `kbuf` is still computed and returned. + * + * If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is + * still generated and stored in `kbuf`. + * + * \param rng_ctx source PRNG context (already initialized). + * \param impl the elliptic curve implementation. + * \param sk the private key structure to fill, or `NULL`. + * \param kbuf the key element buffer, or `NULL`. + * \param curve the curve identifier. + * \return the key data length (in bytes), or zero. + */ +size_t br_ec_keygen(const br_prng_class **rng_ctx, + const br_ec_impl *impl, br_ec_private_key *sk, + void *kbuf, int curve); + +/** + * \brief Compute EC public key from EC private key. + * + * This function uses the provided elliptic curve implementation (`impl`) + * to compute the public key corresponding to the private key held in `sk`. + * The public key point is written into `kbuf`, which is then linked from + * the `*pk` structure. The size of the public key point, i.e. the number + * of bytes used in `kbuf`, is returned. + * + * If `kbuf` is `NULL`, then the public key point is NOT computed, and + * the public key structure `*pk` is unmodified (`pk` may be `NULL` in + * that case). The size of the public key point is still returned. + * + * If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key + * point is computed and stored in `kbuf`, and its size is returned. + * + * If the curve used by the private key is not supported by the curve + * implementation, then this function returns zero. + * + * The private key MUST be valid. An off-range private key value is not + * necessarily detected, and leads to unpredictable results. + * + * \param impl the elliptic curve implementation. + * \param pk the public key structure to fill (or `NULL`). + * \param kbuf the public key point buffer (or `NULL`). + * \param sk the source private key. + * \return the public key point length (in bytes), or zero. + */ +size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, + void *kbuf, const br_ec_private_key *sk); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_hash.h b/template/sysroot/include/bearssl/bearssl_hash.h new file mode 100644 index 0000000..ca4fa26 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_hash.h @@ -0,0 +1,1346 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HASH_H__ +#define BR_BEARSSL_HASH_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hash.h + * + * # Hash Functions + * + * This file documents the API for hash functions. + * + * + * ## Procedural API + * + * For each implemented hash function, of name "`xxx`", the following + * elements are defined: + * + * - `br_xxx_vtable` + * + * An externally defined instance of `br_hash_class`. + * + * - `br_xxx_SIZE` + * + * A macro that evaluates to the output size (in bytes) of the + * hash function. + * + * - `br_xxx_ID` + * + * A macro that evaluates to a symbolic identifier for the hash + * function. Such identifiers are used with HMAC and signature + * algorithm implementations. + * + * NOTE: for the "standard" hash functions defined in [the TLS + * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1), + * the symbolic identifiers match the constants used in TLS, i.e. + * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, + * respectively. + * + * - `br_xxx_context` + * + * Context for an ongoing computation. It is allocated by the + * caller, and a pointer to it is passed to all functions. A + * context contains no interior pointer, so it can be moved around + * and cloned (with a simple `memcpy()` or equivalent) in order to + * capture the function state at some point. Computations that use + * distinct context structures are independent of each other. The + * first field of `br_xxx_context` is always a pointer to the + * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer. + * + * - `br_xxx_init(br_xxx_context *ctx)` + * + * Initialise the provided context. Previous contents of the structure + * are ignored. This calls resets the context to the start of a new + * hash computation; it also sets the first field of the context + * structure (called `vtable`) to a pointer to the statically + * allocated constant `br_xxx_vtable` structure. + * + * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)` + * + * Add some more bytes to the hash computation represented by the + * provided context. + * + * - `br_xxx_out(const br_xxx_context *ctx, void *out)` + * + * Complete the hash computation and write the result in the provided + * buffer. The output buffer MUST be large enough to accommodate the + * result. The context is NOT modified by this operation, so this + * function can be used to get a "partial hash" while still keeping + * the possibility of adding more bytes to the input. + * + * - `br_xxx_state(const br_xxx_context *ctx, void *out)` + * + * Get a copy of the "current state" for the computation so far. For + * MD functions (MD5, SHA-1, SHA-2 family), this is the running state + * resulting from the processing of the last complete input block. + * Returned value is the current input length (in bytes). + * + * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)` + * + * Set the internal state to the provided values. The 'stb' and + * 'count' values shall match that which was obtained from + * `br_xxx_state()`. This restores the hash state only if the state + * values were at an appropriate block boundary. This does NOT set + * the `vtable` pointer in the context. + * + * Context structures can be discarded without any explicit deallocation. + * Hash function implementations are purely software and don't reserve + * any resources outside of the context structure itself. + * + * + * ## Object-Oriented API + * + * For each hash function that follows the procedural API described + * above, an object-oriented API is also provided. In that API, function + * pointers from the vtable (`br_xxx_vtable`) are used. The vtable + * incarnates object-oriented programming. An introduction on the OOP + * concept used here can be read on the BearSSL Web site:
    + *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) + * + * The vtable offers functions called `init()`, `update()`, `out()`, + * `set()` and `set_state()`, which are in fact the functions from + * the procedural API. That vtable also contains two informative fields: + * + * - `context_size` + * + * The size of the context structure (`br_xxx_context`), in bytes. + * This can be used by generic implementations to perform dynamic + * context allocation. + * + * - `desc` + * + * A "descriptor" field that encodes some information on the hash + * function: symbolic identifier, output size, state size, + * internal block size, details on the padding. + * + * Users of this object-oriented API (in particular generic HMAC + * implementations) may make the following assumptions: + * + * - Hash output size is no more than 64 bytes. + * - Hash internal state size is no more than 64 bytes. + * - Internal block size is a power of two, no less than 16 and no more + * than 256. + * + * + * ## Implemented Hash Functions + * + * Implemented hash functions are: + * + * | Function | Name | Output length | State length | + * | :-------- | :------ | :-----------: | :----------: | + * | MD5 | md5 | 16 | 16 | + * | SHA-1 | sha1 | 20 | 20 | + * | SHA-224 | sha224 | 28 | 32 | + * | SHA-256 | sha256 | 32 | 32 | + * | SHA-384 | sha384 | 48 | 64 | + * | SHA-512 | sha512 | 64 | 64 | + * | MD5+SHA-1 | md5sha1 | 36 | 36 | + * + * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the + * same input; in the implementation, the internal data buffer is + * shared, thus making it more memory-efficient than separate MD5 and + * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS + * 1.1.) + * + * + * ## Multi-Hasher + * + * An aggregate hasher is provided, that can compute several standard + * hash functions in parallel. It uses `br_multihash_context` and a + * procedural API. It is configured with the implementations (the vtables) + * that it should use; it will then compute all these hash functions in + * parallel, on the same input. It is meant to be used in cases when the + * hash of an object will be used, but the exact hash function is not + * known yet (typically, streamed processing on X.509 certificates). + * + * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 + * and SHA-512) are supported by the multi-hasher. + * + * + * ## GHASH + * + * GHASH is not a generic hash function; it is a _universal_ hash function, + * which, as the name does not say, means that it CANNOT be used in most + * places where a hash function is needed. GHASH is used within the GCM + * encryption mode, to provide the checked integrity functionality. + * + * A GHASH implementation is basically a function that uses the type defined + * in this file under the name `br_ghash`: + * + * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + * + * The `y` pointer refers to a 16-byte value which is used as input, and + * receives the output of the GHASH invocation. `h` is a 16-byte secret + * value (that serves as key). `data` and `len` define the input data. + * + * Three GHASH implementations are provided, all constant-time, based on + * the use of integer multiplications with appropriate masking to cancel + * carry propagation. + */ + +/** + * \brief Class type for hash function implementations. + * + * A `br_hash_class` instance references the methods implementing a hash + * function. Constant instances of this structure are defined for each + * implemented hash function. Such instances are also called "vtables". + * + * Vtables are used to support object-oriented programming, as + * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). + */ +typedef struct br_hash_class_ br_hash_class; +struct br_hash_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * computing this hash function. + */ + size_t context_size; + + /** + * \brief Descriptor word that contains information about the hash + * function. + * + * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` + * and `BR_HASHDESC_xxx_MASK` to access the specific value, as + * follows: + * + * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK + * + * The defined elements are: + * + * - `ID`: the symbolic identifier for the function, as defined + * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) + * (MD5 = 1, SHA-1 = 2,...). + * + * - `OUT`: hash output size, in bytes. + * + * - `STATE`: internal running state size, in bytes. + * + * - `LBLEN`: base-2 logarithm for the internal block size, as + * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 + * and SHA-256, since these functions use 64-byte blocks; for + * SHA-384 and SHA-512, this is 7, corresponding to their + * 128-byte blocks). + * + * The descriptor may contain a few other flags. + */ + uint32_t desc; + + /** + * \brief Initialisation method. + * + * This method takes as parameter a pointer to a context area, + * that it initialises. The first field of the context is set + * to this vtable; other elements are initialised for a new hash + * computation. + * + * \param ctx pointer to (the first field of) the context. + */ + void (*init)(const br_hash_class **ctx); + + /** + * \brief Data injection method. + * + * The `len` bytes starting at address `data` are injected into + * the running hash computation incarnated by the specified + * context. The context is updated accordingly. It is allowed + * to have `len == 0`, in which case `data` is ignored (and could + * be `NULL`), and nothing happens. + * on the input data. + * + * \param ctx pointer to (the first field of) the context. + * \param data pointer to the first data byte to inject. + * \param len number of bytes to inject. + */ + void (*update)(const br_hash_class **ctx, const void *data, size_t len); + + /** + * \brief Produce hash output. + * + * The hash output corresponding to all data bytes injected in the + * context since the last `init()` call is computed, and written + * in the buffer pointed to by `dst`. The hash output size depends + * on the implemented hash function (e.g. 16 bytes for MD5). + * The context is _not_ modified by this call, so further bytes + * may be afterwards injected to continue the current computation. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the hash output. + */ + void (*out)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Get running state. + * + * This method saves the current running state into the `dst` + * buffer. What constitutes the "running state" depends on the + * hash function; for Merkle-DamgÃ¥rd hash functions (like + * MD5 or SHA-1), this is the output obtained after processing + * each block. The number of bytes injected so far is returned. + * The context is not modified by this call. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the state. + * \return the injected total byte length. + */ + uint64_t (*state)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Set running state. + * + * This methods replaces the running state for the function. + * + * \param ctx pointer to (the first field of) the context. + * \param stb source buffer for the state. + * \param count injected total byte length. + */ + void (*set_state)(const br_hash_class **ctx, + const void *stb, uint64_t count); +}; + +#ifndef BR_DOXYGEN_IGNORE +#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) +#define BR_HASHDESC_ID_OFF 0 +#define BR_HASHDESC_ID_MASK 0xFF + +#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) +#define BR_HASHDESC_OUT_OFF 8 +#define BR_HASHDESC_OUT_MASK 0x7F + +#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) +#define BR_HASHDESC_STATE_OFF 15 +#define BR_HASHDESC_STATE_MASK 0xFF + +#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) +#define BR_HASHDESC_LBLEN_OFF 23 +#define BR_HASHDESC_LBLEN_MASK 0x0F + +#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) +#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) +#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) +#endif + +/* + * Specific hash functions. + * + * Rules for contexts: + * -- No interior pointer. + * -- No pointer to external dynamically allocated resources. + * -- First field is called 'vtable' and is a pointer to a + * const-qualified br_hash_class instance (pointer is set by init()). + * -- SHA-224 and SHA-256 contexts are identical. + * -- SHA-384 and SHA-512 contexts are identical. + * + * Thus, contexts can be moved and cloned to capture the hash function + * current state; and there is no need for any explicit "release" function. + */ + +/** + * \brief Symbolic identifier for MD5. + */ +#define br_md5_ID 1 + +/** + * \brief MD5 output size (in bytes). + */ +#define br_md5_SIZE 16 + +/** + * \brief Constant vtable for MD5. + */ +extern const br_hash_class br_md5_vtable; + +/** + * \brief MD5 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[4]; +#endif +} br_md5_context; + +/** + * \brief MD5 context initialisation. + * + * This function initialises or resets a context for a new MD5 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5_init(br_md5_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5_update(br_md5_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5 output. + * + * The MD5 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5_out(const br_md5_context *ctx, void *out); + +/** + * \brief Save MD5 running state. + * + * The running state for MD5 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5_state(const br_md5_context *ctx, void *out); + +/** + * \brief Restore MD5 running state. + * + * The running state for MD5 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-1. + */ +#define br_sha1_ID 2 + +/** + * \brief SHA-1 output size (in bytes). + */ +#define br_sha1_SIZE 20 + +/** + * \brief Constant vtable for SHA-1. + */ +extern const br_hash_class br_sha1_vtable; + +/** + * \brief SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[5]; +#endif +} br_sha1_context; + +/** + * \brief SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-1 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha1_init(br_sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-1 output. + * + * The SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha1_out(const br_sha1_context *ctx, void *out); + +/** + * \brief Save SHA-1 running state. + * + * The running state for SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); + +/** + * \brief Restore SHA-1 running state. + * + * The running state for SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-224. + */ +#define br_sha224_ID 3 + +/** + * \brief SHA-224 output size (in bytes). + */ +#define br_sha224_SIZE 28 + +/** + * \brief Constant vtable for SHA-224. + */ +extern const br_hash_class br_sha224_vtable; + +/** + * \brief SHA-224 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[8]; +#endif +} br_sha224_context; + +/** + * \brief SHA-224 context initialisation. + * + * This function initialises or resets a context for a new SHA-224 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha224_init(br_sha224_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-224 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-224 output. + * + * The SHA-224 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha224_out(const br_sha224_context *ctx, void *out); + +/** + * \brief Save SHA-224 running state. + * + * The running state for SHA-224 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); + +/** + * \brief Restore SHA-224 running state. + * + * The running state for SHA-224 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha224_set_state(br_sha224_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-256. + */ +#define br_sha256_ID 4 + +/** + * \brief SHA-256 output size (in bytes). + */ +#define br_sha256_SIZE 32 + +/** + * \brief Constant vtable for SHA-256. + */ +extern const br_hash_class br_sha256_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-256 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha256_context; +#else +typedef br_sha224_context br_sha256_context; +#endif + +/** + * \brief SHA-256 context initialisation. + * + * This function initialises or resets a context for a new SHA-256 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha256_init(br_sha256_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-256 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); +#else +#define br_sha256_update br_sha224_update +#endif + +/** + * \brief Compute SHA-256 output. + * + * The SHA-256 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha256_out(const br_sha256_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-256 running state. + * + * The running state for SHA-256 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); +#else +#define br_sha256_state br_sha224_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-256 running state. + * + * The running state for SHA-256 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha256_set_state(br_sha256_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha256_set_state br_sha224_set_state +#endif + +/** + * \brief Symbolic identifier for SHA-384. + */ +#define br_sha384_ID 5 + +/** + * \brief SHA-384 output size (in bytes). + */ +#define br_sha384_SIZE 48 + +/** + * \brief Constant vtable for SHA-384. + */ +extern const br_hash_class br_sha384_vtable; + +/** + * \brief SHA-384 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint64_t val[8]; +#endif +} br_sha384_context; + +/** + * \brief SHA-384 context initialisation. + * + * This function initialises or resets a context for a new SHA-384 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha384_init(br_sha384_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-384 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-384 output. + * + * The SHA-384 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha384_out(const br_sha384_context *ctx, void *out); + +/** + * \brief Save SHA-384 running state. + * + * The running state for SHA-384 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); + +/** + * \brief Restore SHA-384 running state. + * + * The running state for SHA-384 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha384_set_state(br_sha384_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-512. + */ +#define br_sha512_ID 6 + +/** + * \brief SHA-512 output size (in bytes). + */ +#define br_sha512_SIZE 64 + +/** + * \brief Constant vtable for SHA-512. + */ +extern const br_hash_class br_sha512_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-512 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha512_context; +#else +typedef br_sha384_context br_sha512_context; +#endif + +/** + * \brief SHA-512 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha512_init(br_sha512_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-512 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); +#else +#define br_sha512_update br_sha384_update +#endif + +/** + * \brief Compute SHA-512 output. + * + * The SHA-512 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha512_out(const br_sha512_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-512 running state. + * + * The running state for SHA-512 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); +#else +#define br_sha512_state br_sha384_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-512 running state. + * + * The running state for SHA-512 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha512_set_state(br_sha512_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha512_set_state br_sha384_set_state +#endif + +/* + * "md5sha1" is a special hash function that computes both MD5 and SHA-1 + * on the same input, and produces a 36-byte output (MD5 and SHA-1 + * concatenation, in that order). State size is also 36 bytes. + */ + +/** + * \brief Symbolic identifier for MD5+SHA-1. + * + * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the + * same input. It is not one of the functions identified in TLS, so + * we give it a symbolic identifier of value 0. + */ +#define br_md5sha1_ID 0 + +/** + * \brief MD5+SHA-1 output size (in bytes). + */ +#define br_md5sha1_SIZE 36 + +/** + * \brief Constant vtable for MD5+SHA-1. + */ +extern const br_hash_class br_md5sha1_vtable; + +/** + * \brief MD5+SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val_md5[4]; + uint32_t val_sha1[5]; +#endif +} br_md5sha1_context; + +/** + * \brief MD5+SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5sha1_init(br_md5sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5+SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5+SHA-1 output. + * + * The MD5+SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Save MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Restore MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5sha1_set_state(br_md5sha1_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Aggregate context for configurable hash function support. + * + * The `br_hash_compat_context` type is a type which is large enough to + * serve as context for all standard hash functions defined above. + */ +typedef union { + const br_hash_class *vtable; + br_md5_context md5; + br_sha1_context sha1; + br_sha224_context sha224; + br_sha256_context sha256; + br_sha384_context sha384; + br_sha512_context sha512; + br_md5sha1_context md5sha1; +} br_hash_compat_context; + +/* + * The multi-hasher is a construct that handles hashing of the same input + * data with several hash functions, with a single shared input buffer. + * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 + * simultaneously, though which functions are activated depends on + * the set implementation pointers. + */ + +/** + * \brief Multi-hasher context structure. + * + * The multi-hasher runs up to six hash functions in the standard TLS list + * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over + * the same input. + * + * The multi-hasher does _not_ follow the OOP structure with a vtable. + * Instead, it is configured with the vtables of the hash functions it + * should run. Structure fields are not supposed to be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint32_t val_32[25]; + uint64_t val_64[16]; + const br_hash_class *impl[6]; +#endif +} br_multihash_context; + +/** + * \brief Clear a multi-hasher context. + * + * This should always be called once on a given context, _before_ setting + * the implementation pointers. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_zero(br_multihash_context *ctx); + +/** + * \brief Set a hash function implementation. + * + * Implementations shall be set _after_ clearing the context (with + * `br_multihash_zero()`) but _before_ initialising the computation + * (with `br_multihash_init()`). The hash function implementation + * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, + * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove + * an implementation from the multi-hasher. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \param impl the hash function vtable, or `NULL`. + */ +static inline void +br_multihash_setimpl(br_multihash_context *ctx, + int id, const br_hash_class *impl) +{ + /* + * This code relies on hash functions ID being values 1 to 6, + * in the MD5 to SHA-512 order. + */ + ctx->impl[id - 1] = impl; +} + +/** + * \brief Get a hash function implementation. + * + * This function returns the currently configured vtable for a given + * hash function (by symbolic ID). If no such function was configured in + * the provided multi-hasher context, then this function returns `NULL`. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \return the hash function vtable, or `NULL`. + */ +static inline const br_hash_class * +br_multihash_getimpl(const br_multihash_context *ctx, int id) +{ + return ctx->impl[id - 1]; +} + +/** + * \brief Reset a multi-hasher context. + * + * This function prepares the context for a new hashing computation, + * for all implementations configured at that point. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_init(br_multihash_context *ctx); + +/** + * \brief Inject some data bytes in a running multi-hashing computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_multihash_update(br_multihash_context *ctx, + const void *data, size_t len); + +/** + * \brief Compute a hash output from a multi-hasher. + * + * The hash output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `dst`. The hash + * function to use is identified by `id` and must be one of the standard + * hash functions. If that hash function was indeed configured in the + * multi-hasher context, the corresponding hash value is written in + * `dst` and its length (in bytes) is returned. If the hash function + * was _not_ configured, then nothing is written in `dst` and 0 is + * returned. + * + * The context itself is not modified, so extra bytes may be injected + * afterwards to continue the hash computations. + * + * \param ctx pointer to the context structure. + * \param id the hash function symbolic identifier. + * \param dst destination buffer for the hash output. + * \return the hash output length (in bytes), or 0. + */ +size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); + +/** + * \brief Type for a GHASH implementation. + * + * GHASH is a sort of keyed hash meant to be used to implement GCM in + * combination with a block cipher (with 16-byte blocks). + * + * The `y` array has length 16 bytes and is used for input and output; in + * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte + * value that serves as key (it is derived from the encryption key in GCM, + * using the block cipher). The data length (`len`) is expressed in bytes. + * The `y` array is updated. + * + * If the data length is not a multiple of 16, then the data is implicitly + * padded with zeros up to the next multiple of 16. Thus, when using GHASH + * in GCM, this method may be called twice, for the associated data and + * for the ciphertext, respectively; the zero-padding implements exactly + * the GCM rules. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (mixed 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (strict 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, + * but it is expected to be faster on architectures for which the + * 32-bit multiplication opcode does not yield the upper 32 bits of the + * product. It is constant-time (if multiplications are constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (64-bit). + * + * This implementation uses multiplications of 64-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). It is substantially faster than `br_ghash_ctmul()` + * and `br_ghash_ctmul32()` on most 64-bit architectures. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using the `pclmulqdq` opcode (part of the + * AES-NI instructions). + * + * This implementation is available only on x86 platforms where the + * compiler supports the relevant intrinsic functions. Even if the + * compiler supports these functions, the local CPU might not support + * the `pclmulqdq` opcode, meaning that a call will fail with an + * illegal instruction exception. To safely obtain a pointer to this + * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pclmul` GHASH implementation, if available. + * + * If the `pclmul` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pclmul()` function. Otherwise, it will return `0`. + * + * \return the `pclmul` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pclmul_get(void); + +/** + * \brief GHASH implementation using the POWER8 opcodes. + * + * This implementation is available only on POWER8 platforms (and later). + * To safely obtain a pointer to this function when supported (or 0 + * otherwise), use `br_ghash_pwr8_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pwr8` GHASH implementation, if available. + * + * If the `pwr8` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pwr8()` function. Otherwise, it will return `0`. + * + * \return the `pwr8` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pwr8_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_hmac.h b/template/sysroot/include/bearssl/bearssl_hmac.h new file mode 100644 index 0000000..4dc01ca --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_hmac.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HMAC_H__ +#define BR_BEARSSL_HMAC_H__ + +#include +#include + +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hmac.h + * + * # HMAC + * + * HMAC is initialized with a key and an underlying hash function; it + * then fills a "key context". That context contains the processed + * key. + * + * With the key context, a HMAC context can be initialized to process + * the input bytes and obtain the MAC output. The key context is not + * modified during that process, and can be reused. + * + * IMPORTANT: HMAC shall be used only with functions that have the + * following properties: + * + * - hash output size does not exceed 64 bytes; + * - hash internal state size does not exceed 64 bytes; + * - internal block length is a power of 2 between 16 and 256 bytes. + */ + +/** + * \brief HMAC key context. + * + * The HMAC key context is initialised with a hash function implementation + * and a secret key. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_hash_class *dig_vtable; + unsigned char ksi[64], kso[64]; +#endif +} br_hmac_key_context; + +/** + * \brief HMAC key context initialisation. + * + * Initialise the key context with the provided key, using the hash function + * identified by `digest_vtable`. This supports arbitrary key lengths. + * + * \param kc HMAC key context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param key pointer to the HMAC secret key. + * \param key_len HMAC secret key length (in bytes). + */ +void br_hmac_key_init(br_hmac_key_context *kc, + const br_hash_class *digest_vtable, const void *key, size_t key_len); + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC key context. + * + * \param kc HMAC key context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_key_get_digest( + const br_hmac_key_context *kc) +{ + return kc->dig_vtable; +} + +/** + * \brief HMAC computation context. + * + * The HMAC computation context maintains the state for a single HMAC + * computation. It is modified as input bytes are injected. The context + * is caller-allocated and has no release function since it does not + * dynamically allocate external resources. Its contents are opaque. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_hash_compat_context dig; + unsigned char kso[64]; + size_t out_len; +#endif +} br_hmac_context; + +/** + * \brief HMAC computation initialisation. + * + * Initialise a HMAC context with a key context. The key context is + * unmodified. Relevant data from the key context is immediately copied; + * the key context can thus be independently reused, modified or released + * without impacting this HMAC computation. + * + * An explicit output length can be specified; the actual output length + * will be the minimum of that value and the natural HMAC output length. + * If `out_len` is 0, then the natural HMAC output length is selected. The + * "natural output length" is the output length of the underlying hash + * function. + * + * \param ctx HMAC context to initialise. + * \param kc HMAC key context (already initialised with the key). + * \param out_len HMAC output length (0 to select "natural length"). + */ +void br_hmac_init(br_hmac_context *ctx, + const br_hmac_key_context *kc, size_t out_len); + +/** + * \brief Get the HMAC output size. + * + * The HMAC output size is the number of bytes that will actually be + * produced with `br_hmac_out()` with the provided context. This function + * MUST NOT be called on a non-initialised HMAC computation context. + * The returned value is the minimum of the HMAC natural length (output + * size of the underlying hash function) and the `out_len` parameter which + * was used with the last `br_hmac_init()` call on that context (if the + * initialisation `out_len` parameter was 0, then this function will + * return the HMAC natural length). + * + * \param ctx the (already initialised) HMAC computation context. + * \return the HMAC actual output size. + */ +static inline size_t +br_hmac_size(br_hmac_context *ctx) +{ + return ctx->out_len; +} + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC context. + * + * \param hc HMAC context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_get_digest( + const br_hmac_context *hc) +{ + return hc->dig.vtable; +} + +/** + * \brief Inject some bytes in HMAC. + * + * The provided `len` bytes are injected as extra input in the HMAC + * computation incarnated by the `ctx` HMAC context. It is acceptable + * that `len` is zero, in which case `data` is ignored (and may be + * `NULL`) and this function does nothing. + */ +void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); + +/** + * \brief Compute the HMAC output. + * + * The destination buffer MUST be large enough to accommodate the result; + * its length is at most the "natural length" of HMAC (i.e. the output + * length of the underlying hash function). The context is NOT modified; + * further bytes may be processed. Thus, "partial HMAC" values can be + * efficiently obtained. + * + * Returned value is the output length (in bytes). + * + * \param ctx HMAC computation context. + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_out(const br_hmac_context *ctx, void *out); + +/** + * \brief Constant-time HMAC computation. + * + * This function compute the HMAC output in constant time. Some extra + * input bytes are processed, then the output is computed. The extra + * input consists in the `len` bytes pointed to by `data`. The `len` + * parameter must lie between `min_len` and `max_len` (inclusive); + * `max_len` bytes are actually read from `data`. Computing time (and + * memory access pattern) will not depend upon the data byte contents or + * the value of `len`. + * + * The output is written in the `out` buffer, that MUST be large enough + * to receive it. + * + * The difference `max_len - min_len` MUST be less than 230 + * (i.e. about one gigabyte). + * + * This function computes the output properly only if the underlying + * hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 or SHA-512). + * + * The provided context is NOT modified. + * + * \param ctx the (already initialised) HMAC computation context. + * \param data the extra input bytes. + * \param len the extra input length (in bytes). + * \param min_len minimum extra input length (in bytes). + * \param max_len maximum extra input length (in bytes). + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_outCT(const br_hmac_context *ctx, + const void *data, size_t len, size_t min_len, size_t max_len, + void *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_kdf.h b/template/sysroot/include/bearssl/bearssl_kdf.h new file mode 100644 index 0000000..955b843 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_kdf.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_KDF_H__ +#define BR_BEARSSL_KDF_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_kdf.h + * + * # Key Derivation Functions + * + * KDF are functions that takes a variable length input, and provide a + * variable length output, meant to be used to derive subkeys from a + * master key. + * + * ## HKDF + * + * HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869). + * It is based on HMAC, itself using an underlying hash function. Any + * hash function can be used, as long as it is compatible with the rules + * for the HMAC implementation (i.e. output size is 64 bytes or less, hash + * internal state size is 64 bytes or less, and the internal block length is + * a power of 2 between 16 and 256 bytes). HKDF has two phases: + * + * - HKDF-Extract: the input data in ingested, along with a "salt" value. + * + * - HKDF-Expand: the output is produced, from the result of processing + * the input and salt, and using an extra non-secret parameter called + * "info". + * + * The "salt" and "info" strings are non-secret and can be empty. Their role + * is normally to bind the input and output, respectively, to conventional + * identifiers that qualifu them within the used protocol or application. + * + * The implementation defined in this file uses the following functions: + * + * - `br_hkdf_init()`: initialize an HKDF context, with a hash function, + * and the salt. This starts the HKDF-Extract process. + * + * - `br_hkdf_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_hkdf_flip()`: end the HKDF-Extract process, and start the + * HKDF-Expand process. + * + * - `br_hkdf_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + * For correct HKDF processing, the same "info" string must be + * provided for each call. + * + * Note that the HKDF total output size (the number of bytes that + * HKDF-Expand is willing to produce) is limited: if the hash output size + * is _n_ bytes, then the maximum output size is _255*n_. + * + * ## SHAKE + * + * SHAKE is defined in + * [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final) + * under two versions: SHAKE128 and SHAKE256, offering an alleged + * "security level" of 128 and 256 bits, respectively (SHAKE128 is + * about 20 to 25% faster than SHAKE256). SHAKE internally relies on + * the Keccak family of sponge functions, not on any externally provided + * hash function. Contrary to HKDF, SHAKE does not have a concept of + * either a "salt" or an "info" string. The API consists in four + * functions: + * + * - `br_shake_init()`: initialize a SHAKE context for a given + * security level. + * + * - `br_shake_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_shake_flip()`: end the data injection process, and start the + * data production process. + * + * - `br_shake_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + */ + +/** + * \brief HKDF context. + * + * The HKDF context is initialized with a hash function implementation + * and a salt value. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + union { + br_hmac_context hmac_ctx; + br_hmac_key_context prk_ctx; + } u; + unsigned char buf[64]; + size_t ptr; + size_t dig_len; + unsigned chunk_num; +#endif +} br_hkdf_context; + +/** + * \brief HKDF context initialization. + * + * The underlying hash function and salt value are provided. Arbitrary + * salt lengths can be used. + * + * HKDF makes a difference between a salt of length zero, and an + * absent salt (the latter being equivalent to a salt consisting of + * bytes of value zero, of the same length as the hash function output). + * If `salt_len` is zero, then this function assumes that the salt is + * present but of length zero. To specify an _absent_ salt, use + * `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored). + * + * \param hc HKDF context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param salt HKDF-Extract salt. + * \param salt_len HKDF-Extract salt length (in bytes). + */ +void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, + const void *salt, size_t salt_len); + +/** + * \brief The special "absent salt" value for HKDF. + */ +#define BR_HKDF_NO_SALT (&br_hkdf_no_salt) + +#ifndef BR_DOXYGEN_IGNORE +extern const unsigned char br_hkdf_no_salt; +#endif + +/** + * \brief HKDF input injection (HKDF-Extract). + * + * This function injects some more input bytes ("key material") into + * HKDF. This function may be called several times, after `br_hkdf_init()` + * but before `br_hkdf_flip()`. + * + * \param hc HKDF context. + * \param ikm extra input bytes. + * \param ikm_len number of extra input bytes. + */ +void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len); + +/** + * \brief HKDF switch to the HKDF-Expand phase. + * + * This call terminates the HKDF-Extract process (input injection), and + * starts the HKDF-Expand process (output production). + * + * \param hc HKDF context. + */ +void br_hkdf_flip(br_hkdf_context *hc); + +/** + * \brief HKDF output production (HKDF-Expand). + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_hkdf_flip()`. + * + * Returned value is the number of actually produced bytes. The total + * output length is limited to 255 times the output length of the + * underlying hash function. + * + * \param hc HKDF context. + * \param info application specific information string. + * \param info_len application specific information string length (in bytes). + * \param out destination buffer for the HKDF output. + * \param out_len the length of the requested output (in bytes). + * \return the produced output length (in bytes). + */ +size_t br_hkdf_produce(br_hkdf_context *hc, + const void *info, size_t info_len, void *out, size_t out_len); + +/** + * \brief SHAKE context. + * + * The HKDF context is initialized with a "security level". The internal + * notion is called "capacity"; the capacity is twice the security level + * (for instance, SHAKE128 has capacity 256). + * + * The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char dbuf[200]; + size_t dptr; + size_t rate; + uint64_t A[25]; +#endif +} br_shake_context; + +/** + * \brief SHAKE context initialization. + * + * The context is initialized for the provided "security level". + * Internally, this sets the "capacity" to twice the security level; + * thus, for SHAKE128, the `security_level` parameter should be 128, + * which corresponds to a 256-bit capacity. + * + * Allowed security levels are all multiples of 32, from 32 to 768, + * inclusive. Larger security levels imply lower performance; levels + * beyond 256 bits don't make much sense. Standard levels are 128 + * and 256 bits (for SHAKE128 and SHAKE256, respectively). + * + * \param sc SHAKE context to initialise. + * \param security_level security level (in bits). + */ +void br_shake_init(br_shake_context *sc, int security_level); + +/** + * \brief SHAKE input injection. + * + * This function injects some more input bytes ("key material") into + * SHAKE. This function may be called several times, after `br_shake_init()` + * but before `br_shake_flip()`. + * + * \param sc SHAKE context. + * \param data extra input bytes. + * \param len number of extra input bytes. + */ +void br_shake_inject(br_shake_context *sc, const void *data, size_t len); + +/** + * \brief SHAKE switch to production phase. + * + * This call terminates the input injection process, and starts the + * output production process. + * + * \param sc SHAKE context. + */ +void br_shake_flip(br_shake_context *hc); + +/** + * \brief SHAKE output production. + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_shake_flip()`. + * + * There is no practical limit to the number of bytes that may be produced. + * + * \param sc SHAKE context. + * \param out destination buffer for the SHAKE output. + * \param len the length of the requested output (in bytes). + */ +void br_shake_produce(br_shake_context *sc, void *out, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_pem.h b/template/sysroot/include/bearssl/bearssl_pem.h new file mode 100644 index 0000000..8dba582 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_pem.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PEM_H__ +#define BR_BEARSSL_PEM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_pem.h + * + * # PEM Support + * + * PEM is a traditional encoding layer use to store binary objects (in + * particular X.509 certificates, and private keys) in text files. While + * the acronym comes from an old, defunct standard ("Privacy Enhanced + * Mail"), the format has been reused, with some variations, by many + * systems, and is a _de facto_ standard, even though it is not, actually, + * specified in all clarity anywhere. + * + * ## Format Details + * + * BearSSL contains a generic, streamed PEM decoder, which handles the + * following format: + * + * - The input source (a sequence of bytes) is assumed to be the + * encoding of a text file in an ASCII-compatible charset. This + * includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each + * line ends on a newline character (U+000A LINE FEED). The + * U+000D CARRIAGE RETURN characters are ignored, so the code + * accepts both Windows-style and Unix-style line endings. + * + * - Each object begins with a banner that occurs at the start of + * a line; the first banner characters are "`-----BEGIN `" (five + * dashes, the word "BEGIN", and a space). The banner matching is + * not case-sensitive. + * + * - The _object name_ consists in the characters that follow the + * banner start sequence, up to the end of the line, but without + * trailing dashes (in "normal" PEM, there are five trailing + * dashes, but this implementation is not picky about these dashes). + * The BearSSL decoder normalises the name characters to uppercase + * (for ASCII letters only) and accepts names up to 127 characters. + * + * - The object ends with a banner that again occurs at the start of + * a line, and starts with "`-----END `" (again case-insensitive). + * + * - Between that start and end banner, only Base64 data shall occur. + * Base64 converts each sequence of three bytes into four + * characters; the four characters are ASCII letters, digits, "`+`" + * or "`-`" signs, and one or two "`=`" signs may occur in the last + * quartet. Whitespace is ignored (whitespace is any ASCII character + * of code 32 or less, so control characters are whitespace) and + * lines may have arbitrary length; the only restriction is that the + * four characters of a quartet must appear on the same line (no + * line break inside a quartet). + * + * - A single file may contain more than one PEM object. Bytes that + * occur between objects are ignored. + * + * + * ## PEM Decoder API + * + * The PEM decoder offers a state-machine API. The caller allocates a + * decoder context, then injects source bytes. Source bytes are pushed + * with `br_pem_decoder_push()`. The decoder stops accepting bytes when + * it reaches an "event", which is either the start of an object, the + * end of an object, or a decoding error within an object. + * + * The `br_pem_decoder_event()` function is used to obtain the current + * event; it also clears it, thus allowing the decoder to accept more + * bytes. When a object start event is raised, the decoder context + * offers the found object name (normalised to ASCII uppercase). + * + * When an object is reached, the caller must set an appropriate callback + * function, which will receive (by chunks) the decoded object data. + * + * Since the decoder context makes no dynamic allocation, it requires + * no explicit deallocation. + */ + +/** + * \brief PEM decoder context. + * + * Contents are opaque (they should not be accessed directly). + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + const unsigned char *hbuf; + size_t hlen; + + void (*dest)(void *dest_ctx, const void *src, size_t len); + void *dest_ctx; + + unsigned char event; + char name[128]; + unsigned char buf[255]; + size_t ptr; +#endif +} br_pem_decoder_context; + +/** + * \brief Initialise a PEM decoder structure. + * + * \param ctx decoder context to initialise. + */ +void br_pem_decoder_init(br_pem_decoder_context *ctx); + +/** + * \brief Push some bytes into the decoder. + * + * Returned value is the number of bytes actually consumed; this may be + * less than the number of provided bytes if an event is raised. When an + * event is raised, it must be read (with `br_pem_decoder_event()`); + * until the event is read, this function will return 0. + * + * \param ctx decoder context. + * \param data new data bytes. + * \param len number of new data bytes. + * \return the number of bytes actually received (may be less than `len`). + */ +size_t br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Set the receiver for decoded data. + * + * When an object is entered, the provided function (with opaque context + * pointer) will be called repeatedly with successive chunks of decoded + * data for that object. If `dest` is set to 0, then decoded data is + * simply ignored. The receiver can be set at any time, but, in practice, + * it should be called immediately after receiving a "start of object" + * event. + * + * \param ctx decoder context. + * \param dest callback for receiving decoded data. + * \param dest_ctx opaque context pointer for the `dest` callback. + */ +static inline void +br_pem_decoder_setdest(br_pem_decoder_context *ctx, + void (*dest)(void *dest_ctx, const void *src, size_t len), + void *dest_ctx) +{ + ctx->dest = dest; + ctx->dest_ctx = dest_ctx; +} + +/** + * \brief Get the last event. + * + * If an event was raised, then this function returns the event value, and + * also clears it, thereby allowing the decoder to proceed. If no event + * was raised since the last call to `br_pem_decoder_event()`, then this + * function returns 0. + * + * \param ctx decoder context. + * \return the raised event, or 0. + */ +int br_pem_decoder_event(br_pem_decoder_context *ctx); + +/** + * \brief Event: start of object. + * + * This event is raised when the start of a new object has been detected. + * The object name (normalised to uppercase) can be accessed with + * `br_pem_decoder_name()`. + */ +#define BR_PEM_BEGIN_OBJ 1 + +/** + * \brief Event: end of object. + * + * This event is raised when the end of the current object is reached + * (normally, i.e. with no decoding error). + */ +#define BR_PEM_END_OBJ 2 + +/** + * \brief Event: decoding error. + * + * This event is raised when decoding fails within an object. + * This formally closes the current object and brings the decoder back + * to the "out of any object" state. The offending line in the source + * is consumed. + */ +#define BR_PEM_ERROR 3 + +/** + * \brief Get the name of the encountered object. + * + * The encountered object name is defined only when the "start of object" + * event is raised. That name is normalised to uppercase (for ASCII letters + * only) and does not include trailing dashes. + * + * \param ctx decoder context. + * \return the current object name. + */ +static inline const char * +br_pem_decoder_name(br_pem_decoder_context *ctx) +{ + return ctx->name; +} + +/** + * \brief Encode an object in PEM. + * + * This function encodes the provided binary object (`data`, of length `len` + * bytes) into PEM. The `banner` text will be included in the header and + * footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header). + * + * The length (in characters) of the PEM output is returned; that length + * does NOT include the terminating zero, that this function nevertheless + * adds. If using the returned value for allocation purposes, the allocated + * buffer size MUST be at least one byte larger than the returned size. + * + * If `dest` is `NULL`, then the encoding does not happen; however, the + * length of the encoded object is still computed and returned. + * + * The `data` pointer may be `NULL` only if `len` is zero (when encoding + * an object of length zero, which is not very useful), or when `dest` + * is `NULL` (in that case, source data bytes are ignored). + * + * Some `flags` can be specified to alter the encoding behaviour: + * + * - If `BR_PEM_LINE64` is set, then line-breaking will occur after + * every 64 characters of output, instead of the default of 76. + * + * - If `BR_PEM_CRLF` is set, then end-of-line sequence will use + * CR+LF instead of a single LF. + * + * The `data` and `dest` buffers may overlap, in which case the source + * binary data is destroyed in the process. Note that the PEM-encoded output + * is always larger than the source binary. + * + * \param dest the destination buffer (or `NULL`). + * \param data the source buffer (can be `NULL` in some cases). + * \param len the source length (in bytes). + * \param banner the PEM banner expression. + * \param flags the behavioural flags. + * \return the PEM object length (in characters), EXCLUDING the final zero. + */ +size_t br_pem_encode(void *dest, const void *data, size_t len, + const char *banner, unsigned flags); + +/** + * \brief PEM encoding flag: split lines at 64 characters. + */ +#define BR_PEM_LINE64 0x0001 + +/** + * \brief PEM encoding flag: use CR+LF line endings. + */ +#define BR_PEM_CRLF 0x0002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_prf.h b/template/sysroot/include/bearssl/bearssl_prf.h new file mode 100644 index 0000000..fdf608c --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_prf.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PRF_H__ +#define BR_BEARSSL_PRF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_prf.h + * + * # The TLS PRF + * + * The "PRF" is the pseudorandom function used internally during the + * SSL/TLS handshake, notably to expand negotiated shared secrets into + * the symmetric encryption keys that will be used to process the + * application data. + * + * TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This + * is implemented by the `br_tls10_prf()` function. + * + * TLS 1.2 redefines the PRF, using an explicit hash function. The + * `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that + * PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites + * rely on the SHA-256 based PRF, but some use SHA-384. + * + * The PRF always uses as input three parameters: a "secret" (some + * bytes), a "label" (ASCII string), and a "seed" (again some bytes). An + * arbitrary output length can be produced. The "seed" is provided as an + * arbitrary number of binary chunks, that gets internally concatenated. + */ + +/** + * \brief Type for a seed chunk. + * + * Each chunk may have an arbitrary length, and may be empty (no byte at + * all). If the chunk length is zero, then the pointer to the chunk data + * may be `NULL`. + */ +typedef struct { + /** + * \brief Pointer to the chunk data. + */ + const void *data; + + /** + * \brief Chunk length (in bytes). + */ + size_t len; +} br_tls_prf_seed_chunk; + +/** + * \brief PRF implementation for TLS 1.0 and 1.1. + * + * This PRF is the one specified by TLS 1.0 and 1.1. It internally uses + * MD5 and SHA-1. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls10_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-256. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-256. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha256_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-384. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-384. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha384_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * brief A convenient type name for a PRF implementation. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +typedef void (*br_tls_prf_impl)(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_rand.h b/template/sysroot/include/bearssl/bearssl_rand.h new file mode 100644 index 0000000..0a9f544 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_rand.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RAND_H__ +#define BR_BEARSSL_RAND_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rand.h + * + * # Pseudo-Random Generators + * + * A PRNG is a state-based engine that outputs pseudo-random bytes on + * demand. It is initialized with an initial seed, and additional seed + * bytes can be added afterwards. Bytes produced depend on the seeds and + * also on the exact sequence of calls (including sizes requested for + * each call). + * + * + * ## Procedural and OOP API + * + * For the PRNG of name "`xxx`", two API are provided. The _procedural_ + * API defined a context structure `br_xxx_context` and three functions: + * + * - `br_xxx_init()` + * + * Initialise the context with an initial seed. + * + * - `br_xxx_generate()` + * + * Produce some pseudo-random bytes. + * + * - `br_xxx_update()` + * + * Inject some additional seed. + * + * The initialisation function sets the first context field (`vtable`) + * to a pointer to the vtable that supports the OOP API. The OOP API + * provides access to the same functions through function pointers, + * named `init()`, `generate()` and `update()`. + * + * Note that the context initialisation method may accept additional + * parameters, provided as a 'const void *' pointer at API level. These + * additional parameters depend on the implemented PRNG. + * + * + * ## HMAC_DRBG + * + * HMAC_DRBG is defined in [NIST SP 800-90A Revision + * 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf). + * It uses HMAC repeatedly, over some configurable underlying hash + * function. In BearSSL, it is implemented under the "`hmac_drbg`" name. + * The "extra parameters" pointer for context initialisation should be + * set to a pointer to the vtable for the underlying hash function (e.g. + * pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256). + * + * According to the NIST standard, each request shall produce up to + * 219 bits (i.e. 64 kB of data); moreover, the context shall + * be reseeded at least once every 248 requests. This + * implementation does not maintain the reseed counter (the threshold is + * too high to be reached in practice) and does not object to producing + * more than 64 kB in a single request; thus, the code cannot fail, + * which corresponds to the fact that the API has no room for error + * codes. However, this implies that requesting more than 64 kB in one + * `generate()` request, or making more than 248 requests + * without reseeding, is formally out of NIST specification. There is + * no currently known security penalty for exceeding the NIST limits, + * and, in any case, HMAC_DRBG usage in implementing SSL/TLS always + * stays much below these thresholds. + * + * + * ## AESCTR_DRBG + * + * AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is + * meant to be used only in situations where you are desperate for + * speed, and have an hardware-optimized AES/CTR implementation. Whether + * this will yield perceptible improvements depends on what you use the + * pseudorandom bytes for, and how many you want; for instance, RSA key + * pair generation uses a substantial amount of randomness, and using + * AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key + * generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz). + * + * Internally, it uses CTR mode with successive counter values, starting + * at zero (counter value expressed over 128 bits, big-endian convention). + * The counter is not allowed to reach 32768; thus, every 32768*16 bytes + * at most, the `update()` function is run (on an empty seed, if none is + * provided). The `update()` function computes the new AES-128 key by + * applying a custom hash function to the concatenation of a state-dependent + * word (encryption of an all-one block with the current key) and the new + * seed. The custom hash function uses Hirose's construction over AES-256; + * see the comments in `aesctr_drbg.c` for details. + * + * This DRBG does not follow an existing standard, and thus should be + * considered as inadequate for production use until it has been properly + * analysed. + */ + +/** + * \brief Class type for PRNG implementations. + * + * A `br_prng_class` instance references the methods implementing a PRNG. + * Constant instances of this structure are defined for each implemented + * PRNG. Such instances are also called "vtables". + */ +typedef struct br_prng_class_ br_prng_class; +struct br_prng_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * running this PRNG. + */ + size_t context_size; + + /** + * \brief Initialisation method. + * + * The context to initialise is provided as a pointer to its + * first field (the vtable pointer); this function sets that + * first field to a pointer to the vtable. + * + * The extra parameters depend on the implementation; each + * implementation defines what kind of extra parameters it + * expects (if any). + * + * Requirements on the initial seed depend on the implemented + * PRNG. + * + * \param ctx PRNG context to initialise. + * \param params extra parameters for the PRNG. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ + void (*init)(const br_prng_class **ctx, const void *params, + const void *seed, size_t seed_len); + + /** + * \brief Random bytes generation. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx PRNG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ + void (*generate)(const br_prng_class **ctx, void *out, size_t len); + + /** + * \brief Inject additional seed bytes. + * + * The provided seed bytes are added into the PRNG internal + * entropy pool. + * + * \param ctx PRNG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ + void (*update)(const br_prng_class **ctx, + const void *seed, size_t seed_len); +}; + +/** + * \brief Context for HMAC_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char K[64]; + unsigned char V[64]; + const br_hash_class *digest_class; +#endif +} br_hmac_drbg_context; + +/** + * \brief Statically allocated, constant vtable for HMAC_DRBG. + */ +extern const br_prng_class br_hmac_drbg_vtable; + +/** + * \brief HMAC_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The `seed` value is what is called, in NIST terminology, the + * concatenation of the "seed", "nonce" and "personalization string", in + * that order. + * + * The `digest_class` parameter defines the underlying hash function. + * Formally, the NIST standard specifies that the hash function shall + * be only SHA-1 or one of the SHA-2 functions. This implementation also + * works with any other implemented hash function (such as MD5), but + * this is non-standard and therefore not recommended. + * + * \param ctx HMAC_DRBG context to initialise. + * \param digest_class vtable for the underlying hash function. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ +void br_hmac_drbg_init(br_hmac_drbg_context *ctx, + const br_hash_class *digest_class, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with HMAC_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. Formally, requesting + * more than 65536 bytes in one request falls out of specification + * limits (but it won't fail). + * + * \param ctx HMAC_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); + +/** + * \brief Inject additional seed bytes in HMAC_DRBG. + * + * The provided seed bytes are added into the HMAC_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx HMAC_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_hmac_drbg_update(br_hmac_drbg_context *ctx, + const void *seed, size_t seed_len); + +/** + * \brief Get the hash function implementation used by a given instance of + * HMAC_DRBG. + * + * This calls MUST NOT be performed on a context which was not + * previously initialised. + * + * \param ctx HMAC_DRBG context. + * \return the hash function vtable. + */ +static inline const br_hash_class * +br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx) +{ + return ctx->digest_class; +} + +/** + * \brief Type for a provider of entropy seeds. + * + * A "seeder" is a function that is able to obtain random values from + * some source and inject them as entropy seed in a PRNG. A seeder + * shall guarantee that the total entropy of the injected seed is large + * enough to seed a PRNG for purposes of cryptographic key generation + * (i.e. at least 128 bits). + * + * A seeder may report a failure to obtain adequate entropy. Seeders + * shall endeavour to fix themselves transient errors by trying again; + * thus, callers may consider reported errors as permanent. + * + * \param ctx PRNG context to seed. + * \return 1 on success, 0 on error. + */ +typedef int (*br_prng_seeder)(const br_prng_class **ctx); + +/** + * \brief Get a seeder backed by the operating system or hardware. + * + * Get a seeder that feeds on RNG facilities provided by the current + * operating system or hardware. If no such facility is known, then 0 + * is returned. + * + * If `name` is not `NULL`, then `*name` is set to a symbolic string + * that identifies the seeder implementation. If no seeder is returned + * and `name` is not `NULL`, then `*name` is set to a pointer to the + * constant string `"none"`. + * + * \param name receiver for seeder name, or `NULL`. + * \return the system seeder, if available, or 0. + */ +br_prng_seeder br_prng_seeder_system(const char **name); + +/** + * \brief Context for AESCTR_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_aes_gen_ctr_keys sk; + uint32_t cc; +#endif +} br_aesctr_drbg_context; + +/** + * \brief Statically allocated, constant vtable for AESCTR_DRBG. + */ +extern const br_prng_class br_aesctr_drbg_vtable; + +/** + * \brief AESCTR_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The internal AES key is first set to the all-zero key; then, the + * `br_aesctr_drbg_update()` function is called with the provided `seed`. + * The call is performed even if the seed length (`seed_len`) is zero. + * + * The `aesctr` parameter defines the underlying AES/CTR implementation. + * + * \param ctx AESCTR_DRBG context to initialise. + * \param aesctr vtable for the AES/CTR implementation. + * \param seed initial seed (can be `NULL` if `seed_len` is zero). + * \param seed_len initial seed length (in bytes). + */ +void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, + const br_block_ctr_class *aesctr, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with AESCTR_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx AESCTR_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, + void *out, size_t len); + +/** + * \brief Inject additional seed bytes in AESCTR_DRBG. + * + * The provided seed bytes are added into the AESCTR_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx AESCTR_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, + const void *seed, size_t seed_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_rsa.h b/template/sysroot/include/bearssl/bearssl_rsa.h new file mode 100644 index 0000000..0a069fd --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_rsa.h @@ -0,0 +1,1655 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RSA_H__ +#define BR_BEARSSL_RSA_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rsa.h + * + * # RSA + * + * This file documents the RSA implementations provided with BearSSL. + * Note that the SSL engine accesses these implementations through a + * configurable API, so it is possible to, for instance, run a SSL + * server which uses a RSA engine which is not based on this code. + * + * ## Key Elements + * + * RSA public and private keys consist in lists of big integers. All + * such integers are represented with big-endian unsigned notation: + * first byte is the most significant, and the value is positive (so + * there is no dedicated "sign bit"). Public and private key structures + * thus contain, for each such integer, a pointer to the first value byte + * (`unsigned char *`), and a length (`size_t`) which is the number of + * relevant bytes. As a general rule, minimal-length encoding is not + * enforced: values may have extra leading bytes of value 0. + * + * RSA public keys consist in two integers: + * + * - the modulus (`n`); + * - the public exponent (`e`). + * + * RSA private keys, as defined in + * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers: + * + * - the modulus (`n`); + * - the public exponent (`e`); + * - the private exponent (`d`); + * - the first prime factor (`p`); + * - the second prime factor (`q`); + * - the first reduced exponent (`dp`, which is `d` modulo `p-1`); + * - the second reduced exponent (`dq`, which is `d` modulo `q-1`); + * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`). + * + * However, the implementations defined in BearSSL use only five of + * these integers: `p`, `q`, `dp`, `dq` and `iq`. + * + * ## Security Features and Limitations + * + * The implementations contained in BearSSL have the following limitations + * and features: + * + * - They are constant-time. This means that the execution time and + * memory access pattern may depend on the _lengths_ of the private + * key components, but not on their value, nor on the value of + * the operand. Note that this property is not achieved through + * random masking, but "true" constant-time code. + * + * - They support only private keys with two prime factors. RSA private + * keys with three or more prime factors are nominally supported, but + * rarely used; they may offer faster operations, at the expense of + * more code and potentially a reduction in security if there are + * "too many" prime factors. + * + * - The public exponent may have arbitrary length. Of course, it is + * a good idea to keep public exponents small, so that public key + * operations are fast; but, contrary to some widely deployed + * implementations, BearSSL has no problem with public exponents + * longer than 32 bits. + * + * - The two prime factors of the modulus need not have the same length + * (but severely imbalanced factor lengths might reduce security). + * Similarly, there is no requirement that the first factor (`p`) + * be greater than the second factor (`q`). + * + * - Prime factors and modulus must be smaller than a compile-time limit. + * This is made necessary by the use of fixed-size stack buffers, and + * the limit has been adjusted to keep stack usage under 2 kB for the + * RSA operations. Currently, the maximum modulus size is 4096 bits, + * and the maximum prime factor size is 2080 bits. + * + * - The RSA functions themselves do not enforce lower size limits, + * except that which is absolutely necessary for the operation to + * mathematically make sense (e.g. a PKCS#1 v1.5 signature with + * SHA-1 requires a modulus of at least 361 bits). It is up to users + * of this code to enforce size limitations when appropriate (e.g. + * the X.509 validation engine, by default, rejects RSA keys of + * less than 1017 bits). + * + * - Within the size constraints expressed above, arbitrary bit lengths + * are supported. There is no requirement that prime factors or + * modulus have a size multiple of 8 or 16. + * + * - When verifying PKCS#1 v1.5 signatures, both variants of the hash + * function identifying header (with and without the ASN.1 NULL) are + * supported. When producing such signatures, the variant with the + * ASN.1 NULL is used. + * + * ## Implementations + * + * Three RSA implementations are included: + * + * - The **i32** implementation internally represents big integers + * as arrays of 32-bit integers. It is perfunctory and portable, + * but not very efficient. + * + * - The **i31** implementation uses 32-bit integers, each containing + * 31 bits worth of integer data. The i31 implementation is somewhat + * faster than the i32 implementation (the reduced integer size makes + * carry propagation easier) for a similar code footprint, but uses + * very slightly larger stack buffers (about 4% bigger). + * + * - The **i62** implementation is similar to the i31 implementation, + * except that it internally leverages the 64x64->128 multiplication + * opcode. This implementation is available only on architectures + * where such an opcode exists. It is much faster than i31. + * + * - The **i15** implementation uses 16-bit integers, each containing + * 15 bits worth of integer data. Multiplication results fit on + * 32 bits, so this won't use the "widening" multiplication routine + * on ARM Cortex M0/M0+, for much better performance and constant-time + * execution. + */ + +/** + * \brief RSA public key. + * + * The structure references the modulus and the public exponent. Both + * integers use unsigned big-endian representation; extra leading bytes + * of value 0 are allowed. + */ +typedef struct { + /** \brief Modulus. */ + unsigned char *n; + /** \brief Modulus length (in bytes). */ + size_t nlen; + /** \brief Public exponent. */ + unsigned char *e; + /** \brief Public exponent length (in bytes). */ + size_t elen; +} br_rsa_public_key; + +/** + * \brief RSA private key. + * + * The structure references the private factors, reduced private + * exponents, and CRT coefficient. It also contains the bit length of + * the modulus. The big integers use unsigned big-endian representation; + * extra leading bytes of value 0 are allowed. However, the modulus bit + * length (`n_bitlen`) MUST be exact. + */ +typedef struct { + /** \brief Modulus bit length (in bits, exact value). */ + uint32_t n_bitlen; + /** \brief First prime factor. */ + unsigned char *p; + /** \brief First prime factor length (in bytes). */ + size_t plen; + /** \brief Second prime factor. */ + unsigned char *q; + /** \brief Second prime factor length (in bytes). */ + size_t qlen; + /** \brief First reduced private exponent. */ + unsigned char *dp; + /** \brief First reduced private exponent length (in bytes). */ + size_t dplen; + /** \brief Second reduced private exponent. */ + unsigned char *dq; + /** \brief Second reduced private exponent length (in bytes). */ + size_t dqlen; + /** \brief CRT coefficient. */ + unsigned char *iq; + /** \brief CRT coefficient length (in bytes). */ + size_t iqlen; +} br_rsa_private_key; + +/** + * \brief Type for a RSA public key engine. + * + * The public key engine performs the modular exponentiation of the + * provided value with the public exponent. The value is modified in + * place. + * + * The value length (`xlen`) is verified to have _exactly_ the same + * length as the modulus (actual modulus length, without extra leading + * zeros in the modulus representation in memory). If the length does + * not match, then this function returns 0 and `x[]` is unmodified. + * + * It `xlen` is correct, then `x[]` is modified. Returned value is 1 + * on success, 0 on error. Error conditions include an oversized `x[]` + * (the array has the same length as the modulus, but the numerical value + * is not lower than the modulus) and an invalid modulus (e.g. an even + * integer). If an error is reported, then the new contents of `x[]` are + * unspecified. + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA signature verification engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash output length, in bytes. + * + * - The public key. + * + * - An output buffer for the hash value. The caller must still compare + * it with the hash of the data over which the signature is computed. + * + * **Constraints:** + * + * - Hash length MUST be no more than 64 bytes. + * + * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]` + * must have a value in the 0..32 range, inclusive). + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief Type for a RSA signature verification engine (PSS). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same hash function as the one which was + * used to hash the signed message. + * + * - The hashed message (as an array of bytes). + * + * - The PSS salt length (in bytes). + * + * - The public key. + * + * **Constraints:** + * + * - Hash message length MUST be no more than 64 bytes. + * + * Note that, contrary to PKCS#1 v1.5 signature, the hash value of the + * signed data cannot be extracted from the signature; it must be + * provided to the verification function. + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA encryption engine (OAEP). + * + * Parameters are: + * + * - A source of random bytes. The source must be already initialized. + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The public key. + * + * - The destination buffer. Its maximum length (in bytes) is provided; + * if that length is lower than the public key length, then an error + * is reported. + * + * - The source message. + * + * The encrypted message output has exactly the same length as the modulus + * (mathematical length, in bytes, not counting extra leading zeros in the + * modulus representation in the public key). + * + * The source message (`src`, length `src_len`) may overlap with the + * destination buffer (`dst`, length `dst_max_len`). + * + * This function returns the actual encrypted message length, in bytes; + * on error, zero is returned. An error is reported if the output buffer + * is not large enough, or the public is invalid, or the public key + * modulus exceeds the maximum supported RSA size. + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +typedef size_t (*br_rsa_oaep_encrypt)( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief Type for a RSA private key engine. + * + * The `x[]` buffer is modified in place, and its length is inferred from + * the modulus length (`x[]` is assumed to have a length of + * `(sk->n_bitlen+7)/8` bytes). + * + * Returned value is 1 on success, 0 on error. + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_private)(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief Type for a RSA signature generation engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash value computes over the data to sign (its length is + * expressed in bytes). + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash OID and value, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Type for a RSA signature generation engine (PSS). + * + * Parameters are: + * + * - An initialized PRNG for salt generation. If the salt length is + * zero (`salt_len` parameter), then the PRNG is optional (this is + * not the typical case, as the security proof of RSA/PSS is + * tighter when a non-empty salt is used). + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same function as the one used to hash the + * message. + * + * - The hashed message. + * + * - The salt length, in bytes. + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash and salt lengths, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA1 \ + ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A") + +/** + * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA224 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04") + +/** + * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA256 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") + +/** + * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA384 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02") + +/** + * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA512 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") + +/** + * \brief Type for a RSA decryption engine (OAEP). + * + * Parameters are: + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The private key. + * + * - The source and destination buffer. The buffer initially contains + * the encrypted message; the buffer contents are altered, and the + * decrypted message is written at the start of that buffer + * (decrypted message is always shorter than the encrypted message). + * + * If decryption fails in any way, then `*len` is unmodified, and the + * function returns 0. Otherwise, `*len` is set to the decrypted message + * length, and 1 is returned. The implementation is responsible for + * checking that the input message length matches the key modulus length, + * and that the padding is correct. + * + * Implementations MUST use constant-time check of the validity of the + * OAEP padding, at least until the leading byte and hash value have + * been checked. Whether overall decryption worked, and the length of + * the decrypted message, may leak. + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_oaep_decrypt)( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/* + * RSA "i32" engine. Integers are internally represented as arrays of + * 32-bit integers, and the core multiplication primitive is the + * 32x32->64 multiplication. + */ + +/** + * \brief RSA public key engine "i32". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i32" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i32". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i32" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit + * word. This uses slightly more stack space (about 4% more) and code + * space, but it quite faster. + */ + +/** + * \brief RSA public key engine "i31". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i31" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i31". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i31" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i62" engine. Similar to i31, but internal multiplication use + * 64x64->128 multiplications. This is available only on architecture + * that offer such an opcode. + */ + +/** + * \brief RSA public key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get the RSA "i62" implementation (public key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_public br_rsa_i62_public_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (private key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_private br_rsa_i62_private_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_sign br_rsa_i62_pss_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP encryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP decryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void); + +/* + * RSA "i15" engine. Integers are represented as 15-bit integers, so + * the code uses only 32-bit multiplication (no 64-bit result), which + * is vastly faster (and constant-time) on the ARM Cortex M0/M0+. + */ + +/** + * \brief RSA public key engine "i15". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i15" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i15". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i15" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get "default" RSA implementation (public-key operations). + * + * This returns the preferred implementation of RSA (public-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_public br_rsa_public_get_default(void); + +/** + * \brief Get "default" RSA implementation (private-key operations). + * + * This returns the preferred implementation of RSA (private-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_private br_rsa_private_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_sign br_rsa_pss_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP encryption). + * + * This returns the preferred implementation of RSA (OAEP encryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP decryption). + * + * This returns the preferred implementation of RSA (OAEP decryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void); + +/** + * \brief RSA decryption helper, for SSL/TLS. + * + * This function performs the RSA decryption for a RSA-based key exchange + * in a SSL/TLS server. The provided RSA engine is used. The `data` + * parameter points to the value to decrypt, of length `len` bytes. On + * success, the 48-byte pre-master secret is copied into `data`, starting + * at the first byte of that buffer; on error, the contents of `data` + * become indeterminate. + * + * This function first checks that the provided value length (`len`) is + * not lower than 59 bytes, and matches the RSA modulus length; if neither + * of this property is met, then this function returns 0 and the buffer + * is unmodified. + * + * Otherwise, decryption and then padding verification are performed, both + * in constant-time. A decryption error, or a bad padding, or an + * incorrect decrypted value length are reported with a returned value of + * 0; on success, 1 is returned. The caller (SSL server engine) is supposed + * to proceed with a random pre-master secret in case of error. + * + * \param core RSA private key engine. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len length (in bytes) of the data to decrypt. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, + unsigned char *data, size_t len); + +/** + * \brief RSA encryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i15_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i31_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i32_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i62_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief Get buffer size to hold RSA private key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA private key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the private key buffer, in bytes. + */ +#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4)) + +/** + * \brief Get buffer size to hold RSA public key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA public key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the public key buffer, in bytes. + */ +#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3)) + +/** + * \brief Type for RSA key pair generator implementation. + * + * This function generates a new RSA key pair whose modulus has bit + * length `size` bits. The private key elements are written in the + * `kbuf_priv` buffer, and pointer values and length fields to these + * elements are populated in the provided private key structure `sk`. + * Similarly, the public key elements are written in `kbuf_pub`, with + * pointers and lengths set in `pk`. + * + * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the + * private key is set. + * + * If `pubexp` is not zero, then its value will be used as public + * exponent. Valid RSA public exponent values are odd integers + * greater than 1. If `pubexp` is zero, then the public exponent will + * have value 3. + * + * The provided PRNG (`rng_ctx`) must have already been initialized + * and seeded. + * + * Returned value is 1 on success, 0 on error. An error is reported + * if the requested range is outside of the supported key sizes, or + * if an invalid non-zero public exponent value is provided. Supported + * range starts at 512 bits, and up to an implementation-defined + * maximum (by default 4096 bits). Note that key sizes up to 768 bits + * have been broken in practice, and sizes lower than 2048 bits are + * usually considered to be weak and should not be used. + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +typedef uint32_t (*br_rsa_keygen)( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i15" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i15_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i31" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i31_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i62_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief Get the RSA "i62" implementation (key pair generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_keygen br_rsa_i62_keygen_get(void); + +/** + * \brief Get "default" RSA implementation (key pair generation). + * + * This returns the preferred implementation of RSA (key pair generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_keygen br_rsa_keygen_get_default(void); + +/** + * \brief Type for a modulus computing function. + * + * Such a function computes the public modulus from the private key. The + * encoded modulus (unsigned big-endian) is written on `n`, and the size + * (in bytes) is returned. If `n` is `NULL`, then the size is returned but + * the modulus itself is not computed. + * + * If the key size exceeds an internal limit, 0 is returned. + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i15" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i31" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute modulus). + * + * This returns the preferred implementation of RSA (recompute modulus) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void); + +/** + * \brief Type for a public exponent computing function. + * + * Such a function recomputes the public exponent from the private key. + * 0 is returned if any of the following occurs: + * + * - Either `p` or `q` is not equal to 3 modulo 4. + * + * - The public exponent does not fit on 32 bits. + * + * - An internal limit is exceeded. + * + * - The private key is invalid in some way. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds and returns the true + * public exponent. The public exponent is always an odd integer greater + * than 1. + * + * \return the public exponent, or 0. + */ +typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i15" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i31" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute public exponent). + * + * This returns the preferred implementation of RSA (recompute public + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void); + +/** + * \brief Type for a private exponent computing function. + * + * An RSA private key (`br_rsa_private_key`) contains two reduced + * private exponents, which are sufficient to perform private key + * operations. However, standard encoding formats for RSA private keys + * require also a copy of the complete private exponent (non-reduced), + * which this function recomputes. + * + * This function suceeds if all the following conditions hold: + * + * - Both private factors `p` and `q` are equal to 3 modulo 4. + * + * - The provided public exponent `pubexp` is correct, and, in particular, + * is odd, relatively prime to `p-1` and `q-1`, and greater than 1. + * + * - No internal storage limit is exceeded. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds. Note that the API + * restricts the public exponent to a maximum size of 32 bits. + * + * The encoded private exponent is written in `d` (unsigned big-endian + * convention), and the length (in bytes) is returned. If `d` is `NULL`, + * then the exponent is not written anywhere, but the length is still + * returned. On error, 0 is returned. + * + * Not all error conditions are detected when `d` is `NULL`; therefore, the + * returned value shall be checked also when actually producing the value. + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_privexp)(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i15" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i31" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Get "default" RSA implementation (recompute private exponent). + * + * This returns the preferred implementation of RSA (recompute private + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_ssl.h b/template/sysroot/include/bearssl/bearssl_ssl.h new file mode 100644 index 0000000..e91df47 --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_ssl.h @@ -0,0 +1,4296 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_SSL_H__ +#define BR_BEARSSL_SSL_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_prf.h" +#include "bearssl_rand.h" +#include "bearssl_x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ssl.h + * + * # SSL + * + * For an overview of the SSL/TLS API, see [the BearSSL Web + * site](https://www.bearssl.org/api1.html). + * + * The `BR_TLS_*` constants correspond to the standard cipher suites and + * their values in the [IANA + * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). + * + * The `BR_ALERT_*` constants are for standard TLS alert messages. When + * a fatal alert message is sent of received, then the SSL engine context + * status is set to the sum of that alert value (an integer in the 0..255 + * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, + * `BR_ERR_RECV_FATAL_ALERT` for a received alert). + */ + +/** \brief Optimal input buffer size. */ +#define BR_SSL_BUFSIZE_INPUT (16384 + 325) + +/** \brief Optimal output buffer size. */ +#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) + +/** \brief Optimal buffer size for monodirectional engine + (shared input/output buffer). */ +#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT + +/** \brief Optimal buffer size for bidirectional engine + (single buffer split into two separate input/output buffers). */ +#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) + +/* + * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 + * and TLS 1.2). Note that though there is a constant for SSL 3.0, that + * protocol version is not actually supported. + */ + +/** \brief Protocol version: SSL 3.0 (unsupported). */ +#define BR_SSL30 0x0300 +/** \brief Protocol version: TLS 1.0. */ +#define BR_TLS10 0x0301 +/** \brief Protocol version: TLS 1.1. */ +#define BR_TLS11 0x0302 +/** \brief Protocol version: TLS 1.2. */ +#define BR_TLS12 0x0303 + +/* + * Error constants. They are used to report the reason why a context has + * been marked as failed. + * + * Implementation note: SSL-level error codes should be in the 1..31 + * range. The 32..63 range is for certificate decoding and validation + * errors. Received fatal alerts imply an error code in the 256..511 range. + */ + +/** \brief SSL status: no error so far (0). */ +#define BR_ERR_OK 0 + +/** \brief SSL status: caller-provided parameter is incorrect. */ +#define BR_ERR_BAD_PARAM 1 + +/** \brief SSL status: operation requested by the caller cannot be applied + with the current context state (e.g. reading data while outgoing data + is waiting to be sent). */ +#define BR_ERR_BAD_STATE 2 + +/** \brief SSL status: incoming protocol or record version is unsupported. */ +#define BR_ERR_UNSUPPORTED_VERSION 3 + +/** \brief SSL status: incoming record version does not match the expected + version. */ +#define BR_ERR_BAD_VERSION 4 + +/** \brief SSL status: incoming record length is invalid. */ +#define BR_ERR_BAD_LENGTH 5 + +/** \brief SSL status: incoming record is too large to be processed, or + buffer is too small for the handshake message to send. */ +#define BR_ERR_TOO_LARGE 6 + +/** \brief SSL status: decryption found an invalid padding, or the record + MAC is not correct. */ +#define BR_ERR_BAD_MAC 7 + +/** \brief SSL status: no initial entropy was provided, and none can be + obtained from the OS. */ +#define BR_ERR_NO_RANDOM 8 + +/** \brief SSL status: incoming record type is unknown. */ +#define BR_ERR_UNKNOWN_TYPE 9 + +/** \brief SSL status: incoming record or message has wrong type with + regards to the current engine state. */ +#define BR_ERR_UNEXPECTED 10 + +/** \brief SSL status: ChangeCipherSpec message from the peer has invalid + contents. */ +#define BR_ERR_BAD_CCS 12 + +/** \brief SSL status: alert message from the peer has invalid contents + (odd length). */ +#define BR_ERR_BAD_ALERT 13 + +/** \brief SSL status: incoming handshake message decoding failed. */ +#define BR_ERR_BAD_HANDSHAKE 14 + +/** \brief SSL status: ServerHello contains a session ID which is larger + than 32 bytes. */ +#define BR_ERR_OVERSIZED_ID 15 + +/** \brief SSL status: server wants to use a cipher suite that we did + not claim to support. This is also reported if we tried to advertise + a cipher suite that we do not support. */ +#define BR_ERR_BAD_CIPHER_SUITE 16 + +/** \brief SSL status: server wants to use a compression that we did not + claim to support. */ +#define BR_ERR_BAD_COMPRESSION 17 + +/** \brief SSL status: server's max fragment length does not match + client's. */ +#define BR_ERR_BAD_FRAGLEN 18 + +/** \brief SSL status: secure renegotiation failed. */ +#define BR_ERR_BAD_SECRENEG 19 + +/** \brief SSL status: server sent an extension type that we did not + announce, or used the same extension type several times in a single + ServerHello. */ +#define BR_ERR_EXTRA_EXTENSION 20 + +/** \brief SSL status: invalid Server Name Indication contents (when + used by the server, this extension shall be empty). */ +#define BR_ERR_BAD_SNI 21 + +/** \brief SSL status: invalid ServerHelloDone from the server (length + is not 0). */ +#define BR_ERR_BAD_HELLO_DONE 22 + +/** \brief SSL status: internal limit exceeded (e.g. server's public key + is too large). */ +#define BR_ERR_LIMIT_EXCEEDED 23 + +/** \brief SSL status: Finished message from peer does not match the + expected value. */ +#define BR_ERR_BAD_FINISHED 24 + +/** \brief SSL status: session resumption attempt with distinct version + or cipher suite. */ +#define BR_ERR_RESUME_MISMATCH 25 + +/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, + signature algorithm, hash function). */ +#define BR_ERR_INVALID_ALGORITHM 26 + +/** \brief SSL status: invalid signature (on ServerKeyExchange from + server, or in CertificateVerify from client). */ +#define BR_ERR_BAD_SIGNATURE 27 + +/** \brief SSL status: peer's public key does not have the proper type + or is not allowed for requested operation. */ +#define BR_ERR_WRONG_KEY_USAGE 28 + +/** \brief SSL status: client did not send a certificate upon request, + or the client certificate could not be validated. */ +#define BR_ERR_NO_CLIENT_AUTH 29 + +/** \brief SSL status: I/O error or premature close on underlying + transport stream. This error code is set only by the simplified + I/O API ("br_sslio_*"). */ +#define BR_ERR_IO 31 + +/** \brief SSL status: base value for a received fatal alert. + + When a fatal alert is received from the peer, the alert value + is added to this constant. */ +#define BR_ERR_RECV_FATAL_ALERT 256 + +/** \brief SSL status: base value for a sent fatal alert. + + When a fatal alert is sent to the peer, the alert value is added + to this constant. */ +#define BR_ERR_SEND_FATAL_ALERT 512 + +/* ===================================================================== */ + +/** + * \brief Decryption engine for SSL. + * + * When processing incoming records, the SSL engine will use a decryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The decryption engine is responsible for applying decryption, verifying + * MAC, and keeping track of the record sequence number. + */ +typedef struct br_sslrec_in_class_ br_sslrec_in_class; +struct br_sslrec_in_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Test validity of the incoming record length. + * + * This function returns 1 if the announced length for an + * incoming record is valid, 0 otherwise, + * + * \param ctx decryption engine context. + * \param record_len incoming record length. + * \return 1 of a valid length, 0 otherwise. + */ + int (*check_length)(const br_sslrec_in_class *const *ctx, + size_t record_len); + + /** + * \brief Decrypt the incoming record. + * + * This function may assume that the record length is valid + * (it has been previously tested with `check_length()`). + * Decryption is done in place; `*len` is updated with the + * cleartext length, and the address of the first plaintext + * byte is returned. If the record is correct but empty, then + * `*len` is set to 0 and a non-`NULL` pointer is returned. + * + * On decryption/MAC error, `NULL` is returned. + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param payload address of encrypted payload. + * \param len pointer to payload length (updated). + * \return pointer to plaintext, or `NULL` on error. + */ + unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, + int record_type, unsigned version, + void *payload, size_t *len); +}; + +/** + * \brief Encryption engine for SSL. + * + * When building outgoing records, the SSL engine will use an encryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The encryption engine is responsible for applying encryption and MAC, + * and keeping track of the record sequence number. + */ +typedef struct br_sslrec_out_class_ br_sslrec_out_class; +struct br_sslrec_out_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Compute maximum plaintext sizes and offsets. + * + * When this function is called, the `*start` and `*end` + * values contain offsets designating the free area in the + * outgoing buffer for plaintext data; that free area is + * preceded by a 5-byte space which will receive the record + * header. + * + * The `max_plaintext()` function is responsible for adjusting + * both `*start` and `*end` to make room for any record-specific + * header, MAC, padding, and possible split. + * + * \param ctx encryption engine context. + * \param start pointer to start of plaintext offset (updated). + * \param end pointer to start of plaintext offset (updated). + */ + void (*max_plaintext)(const br_sslrec_out_class *const *ctx, + size_t *start, size_t *end); + + /** + * \brief Perform record encryption. + * + * This function encrypts the record. The plaintext address and + * length are provided. Returned value is the start of the + * encrypted record (or sequence of records, if a split was + * performed), _including_ the 5-byte header, and `*len` is + * adjusted to the total size of the record(s), there again + * including the header(s). + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param plaintext address of plaintext. + * \param len pointer to plaintext length (updated). + * \return pointer to start of built record. + */ + unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, + int record_type, unsigned version, + void *plaintext, size_t *len); +}; + +/** + * \brief Context for a no-encryption engine. + * + * The no-encryption engine processes outgoing records during the initial + * handshake, before encryption is applied. + */ +typedef struct { + /** \brief No-encryption engine vtable. */ + const br_sslrec_out_class *vtable; +} br_sslrec_out_clear_context; + +/** \brief Static, constant vtable for the no-encryption engine. */ +extern const br_sslrec_out_class br_sslrec_out_clear_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CBC mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; +struct br_sslrec_in_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC decryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_in_cbc_class **ctx, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for CBC mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; +struct br_sslrec_out_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC encryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_out_cbc_class **ctx, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Context structure for decrypting incoming records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_in_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcdec_class *vtable; + br_aes_gen_cbcdec_keys aes; + br_des_gen_cbcdec_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_in_cbc_context; + +/** + * \brief Static, constant vtable for record decryption with CBC. + */ +extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; + +/** + * \brief Context structure for encrypting outgoing records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_out_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcenc_class *vtable; + br_aes_gen_cbcenc_keys aes; + br_des_gen_cbcenc_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_out_cbc_context; + +/** + * \brief Static, constant vtable for record encryption with CBC. + */ +extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for GCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; +struct br_sslrec_in_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_in_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for GCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; +struct br_sslrec_out_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_out_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Context structure for processing records with GCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_gcm_class *in; + const br_sslrec_out_gcm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctr_class *vtable; + br_aes_gen_ctr_keys aes; + } bc; + br_ghash gh; + unsigned char iv[4]; + unsigned char h[16]; +#endif +} br_sslrec_gcm_context; + +/** + * \brief Static, constant vtable for record decryption with GCM. + */ +extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; + +/** + * \brief Static, constant vtable for record encryption with GCM. + */ +extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; +struct br_sslrec_in_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_in_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Record encryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; +struct br_sslrec_out_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_out_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Context structure for processing records with ChaCha20+Poly1305. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_chapol_class *in; + const br_sslrec_out_chapol_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + unsigned char key[32]; + unsigned char iv[12]; + br_chacha20_run ichacha; + br_poly1305_run ipoly; +#endif +} br_sslrec_chapol_context; + +/** + * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; + +/** + * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; +struct br_sslrec_in_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_in_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Record encryption engine class, for CCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; +struct br_sslrec_out_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_out_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Context structure for processing records with CCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_ccm_class *in; + const br_sslrec_out_ccm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctrcbc_class *vtable; + br_aes_gen_ctrcbc_keys aes; + } bc; + unsigned char iv[4]; + size_t tag_len; +#endif +} br_sslrec_ccm_context; + +/** + * \brief Static, constant vtable for record decryption with CCM. + */ +extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; + +/** + * \brief Static, constant vtable for record encryption with CCM. + */ +extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; + +/* ===================================================================== */ + +/** + * \brief Type for session parameters, to be saved for session resumption. + */ +typedef struct { + /** \brief Session ID buffer. */ + unsigned char session_id[32]; + /** \brief Session ID length (in bytes, at most 32). */ + unsigned char session_id_len; + /** \brief Protocol version. */ + uint16_t version; + /** \brief Cipher suite. */ + uint16_t cipher_suite; + /** \brief Master secret. */ + unsigned char master_secret[48]; +} br_ssl_session_parameters; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Maximum number of cipher suites supported by a client or server. + */ +#define BR_MAX_CIPHER_SUITES 48 +#endif + +/** + * \brief Context structure for SSL engine. + * + * This strucuture is common to the client and server; both the client + * context (`br_ssl_client_context`) and the server context + * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their + * first field. + * + * The engine context manages records, including alerts, closures, and + * transitions to new encryption/MAC algorithms. Processing of handshake + * records is delegated to externally provided code. This structure + * should not be used directly. + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* + * The error code. When non-zero, then the state is "failed" and + * no I/O may occur until reset. + */ + int err; + + /* + * Configured I/O buffers. They are either disjoint, or identical. + */ + unsigned char *ibuf, *obuf; + size_t ibuf_len, obuf_len; + + /* + * Maximum fragment length applies to outgoing records; incoming + * records can be processed as long as they fit in the input + * buffer. It is guaranteed that incoming records at least as big + * as max_frag_len can be processed. + */ + uint16_t max_frag_len; + unsigned char log_max_frag_len; + unsigned char peer_log_max_frag_len; + + /* + * Buffering management registers. + */ + size_t ixa, ixb, ixc; + size_t oxa, oxb, oxc; + unsigned char iomode; + unsigned char incrypt; + + /* + * Shutdown flag: when set to non-zero, incoming record bytes + * will not be accepted anymore. This is used after a close_notify + * has been received: afterwards, the engine no longer claims that + * it could receive bytes from the transport medium. + */ + unsigned char shutdown_recv; + + /* + * 'record_type_in' is set to the incoming record type when the + * record header has been received. + * 'record_type_out' is used to make the next outgoing record + * header when it is ready to go. + */ + unsigned char record_type_in, record_type_out; + + /* + * When a record is received, its version is extracted: + * -- if 'version_in' is 0, then it is set to the received version; + * -- otherwise, if the received version is not identical to + * the 'version_in' contents, then a failure is reported. + * + * This implements the SSL requirement that all records shall + * use the negotiated protocol version, once decided (in the + * ServerHello). It is up to the handshake handler to adjust this + * field when necessary. + */ + uint16_t version_in; + + /* + * 'version_out' is used when the next outgoing record is ready + * to go. + */ + uint16_t version_out; + + /* + * Record handler contexts. + */ + union { + const br_sslrec_in_class *vtable; + br_sslrec_in_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } in; + union { + const br_sslrec_out_class *vtable; + br_sslrec_out_clear_context clear; + br_sslrec_out_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } out; + + /* + * The "application data" flag. Value: + * 0 handshake is in process, no application data acceptable + * 1 application data can be sent and received + * 2 closing, no application data can be sent, but some + * can still be received (and discarded) + */ + unsigned char application_data; + + /* + * Context RNG. + * + * rng_init_done is initially 0. It is set to 1 when the + * basic structure of the RNG is set, and 2 when some + * entropy has been pushed in. The value 2 marks the RNG + * as "properly seeded". + * + * rng_os_rand_done is initially 0. It is set to 1 when + * some seeding from the OS or hardware has been attempted. + */ + br_hmac_drbg_context rng; + int rng_init_done; + int rng_os_rand_done; + + /* + * Supported minimum and maximum versions, and cipher suites. + */ + uint16_t version_min; + uint16_t version_max; + uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; + unsigned char suites_num; + + /* + * For clients, the server name to send as a SNI extension. For + * servers, the name received in the SNI extension (if any). + */ + char server_name[256]; + + /* + * "Security parameters". These are filled by the handshake + * handler, and used when switching encryption state. + */ + unsigned char client_random[32]; + unsigned char server_random[32]; + br_ssl_session_parameters session; + + /* + * ECDHE elements: curve and point from the peer. The server also + * uses that buffer for the point to send to the client. + */ + unsigned char ecdhe_curve; + unsigned char ecdhe_point[133]; + unsigned char ecdhe_point_len; + + /* + * Secure renegotiation (RFC 5746): 'reneg' can be: + * 0 first handshake (server support is not known) + * 1 peer does not support secure renegotiation + * 2 peer supports secure renegotiation + * + * The saved_finished buffer contains the client and the + * server "Finished" values from the last handshake, in + * that order (12 bytes each). + */ + unsigned char reneg; + unsigned char saved_finished[24]; + + /* + * Behavioural flags. + */ + uint32_t flags; + + /* + * Context variables for the handshake processor. The 'pad' must + * be large enough to accommodate an RSA-encrypted pre-master + * secret, or an RSA signature; since we want to support up to + * RSA-4096, this means at least 512 bytes. (Other pad usages + * require its length to be at least 256.) + */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + unsigned char pad[512]; + unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; + size_t hlen_in, hlen_out; + void (*hsrun)(void *ctx); + + /* + * The 'action' value communicates OOB information between the + * engine and the handshake processor. + * + * From the engine: + * 0 invocation triggered by I/O + * 1 invocation triggered by explicit close + * 2 invocation triggered by explicit renegotiation + */ + unsigned char action; + + /* + * State for alert messages. Value is either 0, or the value of + * the alert level byte (level is either 1 for warning, or 2 for + * fatal; we convert all other values to 'fatal'). + */ + unsigned char alert; + + /* + * Closure flags. This flag is set when a close_notify has been + * received from the peer. + */ + unsigned char close_received; + + /* + * Multi-hasher for the handshake messages. The handshake handler + * is responsible for resetting it when appropriate. + */ + br_multihash_context mhash; + + /* + * Pointer to the X.509 engine. The engine is supposed to be + * already initialized. It is used to validate the peer's + * certificate. + */ + const br_x509_class **x509ctx; + + /* + * Certificate chain to send. This is used by both client and + * server, when they send their respective Certificate messages. + * If chain_len is 0, then chain may be NULL. + */ + const br_x509_certificate *chain; + size_t chain_len; + const unsigned char *cert_cur; + size_t cert_len; + + /* + * List of supported protocol names (ALPN extension). If unset, + * (number of names is 0), then: + * - the client sends no ALPN extension; + * - the server ignores any incoming ALPN extension. + * + * Otherwise: + * - the client sends an ALPN extension with all the names; + * - the server selects the first protocol in its list that + * the client also supports, or fails (fatal alert 120) + * if the client sends an ALPN extension and there is no + * match. + * + * The 'selected_protocol' field contains 1+n if the matching + * name has index n in the list (the value is 0 if no match was + * performed, e.g. the peer did not send an ALPN extension). + */ + const char **protocol_names; + uint16_t protocol_names_num; + uint16_t selected_protocol; + + /* + * Pointers to implementations; left to NULL for unsupported + * functions. For the raw hash functions, implementations are + * referenced from the multihasher (mhash field). + */ + br_tls_prf_impl prf10; + br_tls_prf_impl prf_sha256; + br_tls_prf_impl prf_sha384; + const br_block_cbcenc_class *iaes_cbcenc; + const br_block_cbcdec_class *iaes_cbcdec; + const br_block_ctr_class *iaes_ctr; + const br_block_ctrcbc_class *iaes_ctrcbc; + const br_block_cbcenc_class *ides_cbcenc; + const br_block_cbcdec_class *ides_cbcdec; + br_ghash ighash; + br_chacha20_run ichacha; + br_poly1305_run ipoly; + const br_sslrec_in_cbc_class *icbc_in; + const br_sslrec_out_cbc_class *icbc_out; + const br_sslrec_in_gcm_class *igcm_in; + const br_sslrec_out_gcm_class *igcm_out; + const br_sslrec_in_chapol_class *ichapol_in; + const br_sslrec_out_chapol_class *ichapol_out; + const br_sslrec_in_ccm_class *iccm_in; + const br_sslrec_out_ccm_class *iccm_out; + const br_ec_impl *iec; + br_rsa_pkcs1_vrfy irsavrfy; + br_ecdsa_vrfy iecdsa; +#endif +} br_ssl_engine_context; + +/** + * \brief Get currently defined engine behavioural flags. + * + * \param cc SSL engine context. + * \return the flags. + */ +static inline uint32_t +br_ssl_engine_get_flags(br_ssl_engine_context *cc) +{ + return cc->flags; +} + +/** + * \brief Set all engine behavioural flags. + * + * \param cc SSL engine context. + * \param flags new value for all flags. + */ +static inline void +br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags = flags; +} + +/** + * \brief Set some engine behavioural flags. + * + * The flags set in the `flags` parameter are set in the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags additional set flags. + */ +static inline void +br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags |= flags; +} + +/** + * \brief Clear some engine behavioural flags. + * + * The flags set in the `flags` parameter are cleared from the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags flags to remove. + */ +static inline void +br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags &= ~flags; +} + +/** + * \brief Behavioural flag: enforce server preferences. + * + * If this flag is set, then the server will enforce its own cipher suite + * preference order; otherwise, it follows the client preferences. + */ +#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) + +/** + * \brief Behavioural flag: disable renegotiation. + * + * If this flag is set, then renegotiations are rejected unconditionally: + * they won't be honoured if asked for programmatically, and requests from + * the peer are rejected. + */ +#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) + +/** + * \brief Behavioural flag: tolerate lack of client authentication. + * + * If this flag is set in a server and the server requests a client + * certificate, but the authentication fails (the client does not send + * a certificate, or the client's certificate chain cannot be validated), + * then the connection keeps on. Without this flag, a failed client + * authentication terminates the connection. + * + * Notes: + * + * - If the client's certificate can be validated and its public key is + * supported, then a wrong signature value terminates the connection + * regardless of that flag. + * + * - If using full-static ECDH, then a failure to validate the client's + * certificate prevents the handshake from succeeding. + */ +#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) + +/** + * \brief Behavioural flag: fail on application protocol mismatch. + * + * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) + * allows the client to send a list of application protocol names, and + * the server to select one. A mismatch is one of the following occurrences: + * + * - On the client: the client sends a list of names, the server + * responds with a protocol name which is _not_ part of the list of + * names sent by the client. + * + * - On the server: the client sends a list of names, and the server + * is also configured with a list of names, but there is no common + * protocol name between the two lists. + * + * Normal behaviour in case of mismatch is to report no matching name + * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. + * If the flag is set, then a mismatch implies a protocol failure (if + * the mismatch is detected by the server, it will send a fatal alert). + * + * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` + * may still return `NULL` if the client or the server does not send an + * ALPN extension at all. + */ +#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) + +/** + * \brief Set the minimum and maximum supported protocol versions. + * + * The two provided versions MUST be supported by the implementation + * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower + * than `version_min`. + * + * \param cc SSL engine context. + * \param version_min minimum supported TLS version. + * \param version_max maximum supported TLS version. + */ +static inline void +br_ssl_engine_set_versions(br_ssl_engine_context *cc, + unsigned version_min, unsigned version_max) +{ + cc->version_min = (uint16_t)version_min; + cc->version_max = (uint16_t)version_max; +} + +/** + * \brief Set the list of cipher suites advertised by this context. + * + * The provided array is copied into the context. It is the caller + * responsibility to ensure that all provided suites will be supported + * by the context. The engine context has enough room to receive _all_ + * suites supported by the implementation. The provided array MUST NOT + * contain duplicates. + * + * If the engine is for a client, the "signaling" pseudo-cipher suite + * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the + * calling application is performing a voluntary downgrade (voluntary + * downgrades are not recommended, but if such a downgrade is done, then + * adding the fallback pseudo-suite is a good idea). + * + * \param cc SSL engine context. + * \param suites cipher suites. + * \param suites_num number of cipher suites. + */ +void br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num); + +/** + * \brief Set the X.509 engine. + * + * The caller shall ensure that the X.509 engine is properly initialised. + * + * \param cc SSL engine context. + * \param x509ctx X.509 certificate validation context. + */ +static inline void +br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) +{ + cc->x509ctx = x509ctx; +} + +/** + * \brief Set the supported protocol names. + * + * Protocol names are part of the ALPN extension ([RFC + * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a + * character string, containing no more than 255 characters (256 with the + * terminating zero). When names are set, then: + * + * - The client will send an ALPN extension, containing the names. If + * the server responds with an ALPN extension, the client will verify + * that the response contains one of its name, and report that name + * through `br_ssl_engine_get_selected_protocol()`. + * + * - The server will parse incoming ALPN extension (from clients), and + * try to find a common protocol; if none is found, the connection + * is aborted with a fatal alert. On match, a response ALPN extension + * is sent, and name is reported through + * `br_ssl_engine_get_selected_protocol()`. + * + * The provided array is linked in, and must remain valid while the + * connection is live. + * + * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters + * (excluding the terminating 0). + * + * \param ctx SSL engine context. + * \param names list of protocol names (zero-terminated). + * \param num number of protocol names (MUST be 1 or more). + */ +static inline void +br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, + const char **names, size_t num) +{ + ctx->protocol_names = names; + ctx->protocol_names_num = (uint16_t)num; +} + +/** + * \brief Get the selected protocol. + * + * If this context was initialised with a non-empty list of protocol + * names, and both client and server sent ALPN extensions during the + * handshake, and a common name was found, then that name is returned. + * Otherwise, `NULL` is returned. + * + * The returned pointer is one of the pointers provided to the context + * with `br_ssl_engine_set_protocol_names()`. + * + * \return the selected protocol, or `NULL`. + */ +static inline const char * +br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) +{ + unsigned k; + + k = ctx->selected_protocol; + return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; +} + +/** + * \brief Set a hash function implementation (by ID). + * + * Hash functions set with this call will be used for SSL/TLS specific + * usages, not X.509 certificate validation. Only "standard" hash functions + * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` + * is `NULL`, then the hash function support is removed, not added. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_hash(br_ssl_engine_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Get a hash function implementation (by ID). + * + * This function retrieves a hash function implementation which was + * set with `br_ssl_engine_set_hash()`. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \return the hash function implementation (or `NULL`). + */ +static inline const br_hash_class * +br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) +{ + return br_multihash_getimpl(&ctx->mhash, id); +} + +/** + * \brief Set the PRF implementation (for TLS 1.0 and 1.1). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the PRF used in TLS 1.0 and 1.1. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf10 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-256 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha256 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-384 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha384 = impl; +} + +/** + * \brief Set the AES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc AES/CBC encryption implementation (or `NULL`). + * \param impl_dec AES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->iaes_cbcenc = impl_enc; + cc->iaes_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, + const br_block_ctr_class *impl) +{ + cc->iaes_ctr = impl; +} + +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + +/** + * \brief Set the DES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc DES/CBC encryption implementation (or `NULL`). + * \param impl_dec DES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->ides_cbcenc = impl_enc; + cc->ides_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the GHASH implementation (used in GCM mode). + * + * \param cc SSL engine context. + * \param impl GHASH implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) +{ + cc->ighash = impl; +} + +/** + * \brief Set the ChaCha20 implementation. + * + * \param cc SSL engine context. + * \param ichacha ChaCha20 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, + br_chacha20_run ichacha) +{ + cc->ichacha = ichacha; +} + +/** + * \brief Set the Poly1305 implementation. + * + * \param cc SSL engine context. + * \param ipoly Poly1305 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, + br_poly1305_run ipoly) +{ + cc->ipoly = ipoly; +} + +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR+CBC implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, + const br_block_ctrcbc_class *impl) +{ + cc->iaes_ctrcbc = impl; +} + +/** + * \brief Set the "default" implementations for AES/CCM. + * + * This function configures in the engine the AES/CTR+CBC + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for CCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); + +/** + * \brief Set the record encryption and decryption engines for CBC + HMAC. + * + * \param cc SSL engine context. + * \param impl_in record CBC decryption implementation (or `NULL`). + * \param impl_out record CBC encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_cbc(br_ssl_engine_context *cc, + const br_sslrec_in_cbc_class *impl_in, + const br_sslrec_out_cbc_class *impl_out) +{ + cc->icbc_in = impl_in; + cc->icbc_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for GCM. + * + * \param cc SSL engine context. + * \param impl_in record GCM decryption implementation (or `NULL`). + * \param impl_out record GCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_gcm(br_ssl_engine_context *cc, + const br_sslrec_in_gcm_class *impl_in, + const br_sslrec_out_gcm_class *impl_out) +{ + cc->igcm_in = impl_in; + cc->igcm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for CCM. + * + * \param cc SSL engine context. + * \param impl_in record CCM decryption implementation (or `NULL`). + * \param impl_out record CCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ccm(br_ssl_engine_context *cc, + const br_sslrec_in_ccm_class *impl_in, + const br_sslrec_out_ccm_class *impl_out) +{ + cc->iccm_in = impl_in; + cc->iccm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for + * ChaCha20+Poly1305. + * + * \param cc SSL engine context. + * \param impl_in record ChaCha20 decryption implementation (or `NULL`). + * \param impl_out record ChaCha20 encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chapol(br_ssl_engine_context *cc, + const br_sslrec_in_chapol_class *impl_in, + const br_sslrec_out_chapol_class *impl_out) +{ + cc->ichapol_in = impl_in; + cc->ichapol_out = impl_out; +} + +/** + * \brief Set the EC implementation. + * + * The elliptic curve implementation will be used for ECDH and ECDHE + * cipher suites, and for ECDSA support. + * + * \param cc SSL engine context. + * \param iec EC implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) +{ + cc->iec = iec; +} + +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + +/** + * \brief Set the RSA signature verification implementation. + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, and that certificate contains a RSA key). + * + * \param cc SSL engine context. + * \param irsavrfy RSA signature verification implementation. + */ +static inline void +br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) +{ + cc->irsavrfy = irsavrfy; +} + +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + +/* + * \brief Set the ECDSA implementation (signature verification). + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, that certificate contains an EC key, + * and full-static ECDH is not used). + * + * The ECDSA implementation will use the EC core implementation configured + * in the engine context. + * + * \param cc client context. + * \param iecdsa ECDSA verification implementation. + */ +static inline void +br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) +{ + cc->iecdsa = iecdsa; +} + +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + +/** + * \brief Set the I/O buffer for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * The provided buffer will be used as long as the engine context is + * used. The caller is responsible for keeping it available. + * + * If `bidi` is 0, then the engine will operate in half-duplex mode + * (it won't be able to send data while there is unprocessed incoming + * data in the buffer, and it won't be able to receive data while there + * is unsent data in the buffer). The optimal buffer size in half-duplex + * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra + * bytes are ignored. If the buffer is smaller, then this limits the + * capacity of the engine to support all allowed record sizes. + * + * If `bidi` is 1, then the engine will split the buffer into two + * parts, for separate handling of outgoing and incoming data. This + * enables full-duplex processing, but requires more RAM. The optimal + * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the + * buffer is larger, then extra bytes are ignored. If the buffer is + * smaller, then the split will favour the incoming part, so that + * interoperability is maximised. + * + * \param cc SSL engine context + * \param iobuf I/O buffer. + * \param iobuf_len I/O buffer length (in bytes). + * \param bidi non-zero for full-duplex mode. + */ +void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, + void *iobuf, size_t iobuf_len, int bidi); + +/** + * \brief Set the I/O buffers for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * This function is similar to `br_ssl_engine_set_buffer()`, except + * that it enforces full-duplex mode, and the two I/O buffers are + * provided as separate chunks. + * + * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` + * evaluate to the optimal (maximum) sizes for the input and output + * buffer, respectively. + * + * \param cc SSL engine context + * \param ibuf input buffer. + * \param ibuf_len input buffer length (in bytes). + * \param obuf output buffer. + * \param obuf_len output buffer length (in bytes). + */ +void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); + +/** + * \brief Inject some "initial entropy" in the context. + * + * This entropy will be added to what can be obtained from the + * underlying operating system, if that OS is supported. + * + * This function may be called several times; all injected entropy chunks + * are cumulatively mixed. + * + * If entropy gathering from the OS is supported and compiled in, then this + * step is optional. Otherwise, it is mandatory to inject randomness, and + * the caller MUST take care to push (as one or several successive calls) + * enough entropy to achieve cryptographic resistance (at least 80 bits, + * preferably 128 or more). The engine will report an error if no entropy + * was provided and none can be obtained from the OS. + * + * Take care that this function cannot assess the cryptographic quality of + * the provided bytes. + * + * In all generality, "entropy" must here be considered to mean "that + * which the attacker cannot predict". If your OS/architecture does not + * have a suitable source of randomness, then you can make do with the + * combination of a large enough secret value (possibly a copy of an + * asymmetric private key that you also store on the system) AND a + * non-repeating value (e.g. current time, provided that the local clock + * cannot be reset or altered by the attacker). + * + * \param cc SSL engine context. + * \param data extra entropy to inject. + * \param len length of the extra data (in bytes). + */ +void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len); + +/** + * \brief Get the "server name" in this engine. + * + * For clients, this is the name provided with `br_ssl_client_reset()`; + * for servers, this is the name received from the client as part of the + * ClientHello message. If there is no such name (e.g. the client did + * not send an SNI extension) then the returned string is empty + * (returned pointer points to a byte of value 0). + * + * The returned pointer refers to a buffer inside the context, which may + * be overwritten as part of normal SSL activity (even within the same + * connection, if a renegotiation occurs). + * + * \param cc SSL engine context. + * \return the server name (possibly empty). + */ +static inline const char * +br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) +{ + return cc->server_name; +} + +/** + * \brief Get the protocol version. + * + * This function returns the protocol version that is used by the + * engine. That value is set after sending (for a server) or receiving + * (for a client) the ServerHello message. + * + * \param cc SSL engine context. + * \return the protocol version. + */ +static inline unsigned +br_ssl_engine_get_version(const br_ssl_engine_context *cc) +{ + return cc->session.version; +} + +/** + * \brief Get a copy of the session parameters. + * + * The session parameters are filled during the handshake, so this + * function shall not be called before completion of the handshake. + * The initial handshake is completed when the context first allows + * application data to be injected. + * + * This function copies the current session parameters into the provided + * structure. Beware that the session parameters include the master + * secret, which is sensitive data, to handle with great care. + * + * \param cc SSL engine context. + * \param pp destination structure for the session parameters. + */ +static inline void +br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, + br_ssl_session_parameters *pp) +{ + memcpy(pp, &cc->session, sizeof *pp); +} + +/** + * \brief Set the session parameters to the provided values. + * + * This function is meant to be used in the client, before doing a new + * handshake; a session resumption will be attempted with these + * parameters. In the server, this function has no effect. + * + * \param cc SSL engine context. + * \param pp source structure for the session parameters. + */ +static inline void +br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, + const br_ssl_session_parameters *pp) +{ + memcpy(&cc->session, pp, sizeof *pp); +} + +/** + * \brief Get identifier for the curve used for key exchange. + * + * If the cipher suite uses ECDHE, then this function returns the + * identifier for the curve used for transient parameters. This is + * defined during the course of the handshake, when the ServerKeyExchange + * is sent (on the server) or received (on the client). If the + * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key + * exchange), then this value is indeterminate. + * + * @param cc SSL engine context. + * @return the ECDHE curve identifier. + */ +static inline int +br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) +{ + return cc->ecdhe_curve; +} + +/** + * \brief Get the current engine state. + * + * An SSL engine (client or server) has, at any time, a state which is + * the combination of zero, one or more of these flags: + * + * - `BR_SSL_CLOSED` + * + * Engine is finished, no more I/O (until next reset). + * + * - `BR_SSL_SENDREC` + * + * Engine has some bytes to send to the peer. + * + * - `BR_SSL_RECVREC` + * + * Engine expects some bytes from the peer. + * + * - `BR_SSL_SENDAPP` + * + * Engine may receive application data to send (or flush). + * + * - `BR_SSL_RECVAPP` + * + * Engine has obtained some application data from the peer, + * that should be read by the caller. + * + * If no flag at all is set (state value is 0), then the engine is not + * fully initialised yet. + * + * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag + * is set. To distinguish between a normal closure and an error, use + * `br_ssl_engine_last_error()`. + * + * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually + * exclusive: the input buffer, at any point, either accumulates + * plaintext data, or contains an assembled record that is being sent. + * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. + * This may change in a future library version. + * + * \param cc SSL engine context. + * \return the current engine state. + */ +unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); + +/** \brief SSL engine state: closed or failed. */ +#define BR_SSL_CLOSED 0x0001 +/** \brief SSL engine state: record data is ready to be sent to the peer. */ +#define BR_SSL_SENDREC 0x0002 +/** \brief SSL engine state: engine may receive records from the peer. */ +#define BR_SSL_RECVREC 0x0004 +/** \brief SSL engine state: engine may accept application data to send. */ +#define BR_SSL_SENDAPP 0x0008 +/** \brief SSL engine state: engine has received application data. */ +#define BR_SSL_RECVAPP 0x0010 + +/** + * \brief Get the engine error indicator. + * + * The error indicator is `BR_ERR_OK` (0) if no error was encountered + * since the last call to `br_ssl_client_reset()` or + * `br_ssl_server_reset()`. Other status values are "sticky": they + * remain set, and prevent all I/O activity, until cleared. Only the + * reset calls clear the error indicator. + * + * \param cc SSL engine context. + * \return 0, or a non-zero error code. + */ +static inline int +br_ssl_engine_last_error(const br_ssl_engine_context *cc) +{ + return cc->err; +} + +/* + * There are four I/O operations, each identified by a symbolic name: + * + * sendapp inject application data in the engine + * recvapp retrieving application data from the engine + * sendrec sending records on the transport medium + * recvrec receiving records from the transport medium + * + * Terminology works thus: in a layered model where the SSL engine sits + * between the application and the network, "send" designates operations + * where bytes flow from application to network, and "recv" for the + * reverse operation. Application data (the plaintext that is to be + * conveyed through SSL) is "app", while encrypted records are "rec". + * Note that from the SSL engine point of view, "sendapp" and "recvrec" + * designate bytes that enter the engine ("inject" operation), while + * "recvapp" and "sendrec" designate bytes that exit the engine + * ("extract" operation). + * + * For the operation 'xxx', two functions are defined: + * + * br_ssl_engine_xxx_buf + * Returns a pointer and length to the buffer to use for that + * operation. '*len' is set to the number of bytes that may be read + * from the buffer (extract operation) or written to the buffer + * (inject operation). If no byte may be exchanged for that operation + * at that point, then '*len' is set to zero, and NULL is returned. + * The engine state is unmodified by this call. + * + * br_ssl_engine_xxx_ack + * Informs the engine that 'len' bytes have been read from the buffer + * (extract operation) or written to the buffer (inject operation). + * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed + * that which was obtained from a preceding br_ssl_engine_xxx_buf() + * call. + */ + +/** + * \brief Get buffer for application data to send. + * + * If the engine is ready to accept application data to send to the + * peer, then this call returns a pointer to the buffer where such + * data shall be written, and its length is written in `*len`. + * Otherwise, `*len` is set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data output buffer length, or 0. + * \return the application data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new application data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_sendapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for received application data. + * + * If the engine has received application data from the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data input buffer length, or 0. + * \return the application data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some received application data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_recvapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for record data to send. + * + * If the engine has prepared some records to send to the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data output buffer length, or 0. + * \return the record data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some sent record data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_sendrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for incoming records. + * + * If the engine is ready to accept records from the peer, then this + * call returns a pointer to the buffer where such data shall be + * written, and its length is written in `*len`. Otherwise, `*len` is + * set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data input buffer length, or 0. + * \return the record data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new record data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_recvrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Flush buffered application data. + * + * If some application data has been buffered in the engine, then wrap + * it into a record and mark it for sending. If no application data has + * been buffered but the engine would be ready to accept some, AND the + * `force` parameter is non-zero, then an empty record is assembled and + * marked for sending. In all other cases, this function does nothing. + * + * Empty records are technically legal, but not all existing SSL/TLS + * implementations support them. Empty records can be useful as a + * transparent "keep-alive" mechanism to maintain some low-level + * network activity. + * + * \param cc SSL engine context. + * \param force non-zero to force sending an empty record. + */ +void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); + +/** + * \brief Initiate a closure. + * + * If, at that point, the context is open and in ready state, then a + * `close_notify` alert is assembled and marked for sending; this + * triggers the closure protocol. Otherwise, no such alert is assembled. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_close(br_ssl_engine_context *cc); + +/** + * \brief Initiate a renegotiation. + * + * If the engine is failed or closed, or if the peer is known not to + * support secure renegotiation (RFC 5746), or if renegotiations have + * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there + * is buffered incoming application data, then this function returns 0 + * and nothing else happens. + * + * Otherwise, this function returns 1, and a renegotiation attempt is + * triggered (if a handshake is already ongoing at that point, then + * no new handshake is triggered). + * + * \param cc SSL engine context. + * \return 1 on success, 0 on error. + */ +int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); + +/** + * \brief Export key material from a connected SSL engine (RFC 5705). + * + * This calls compute a secret key of arbitrary length from the master + * secret of a connected SSL engine. If the provided context is not + * currently in "application data" state (initial handshake is not + * finished, another handshake is ongoing, or the connection failed or + * was closed), then this function returns 0. Otherwise, a secret key of + * length `len` bytes is computed and written in the buffer pointed to + * by `dst`, and 1 is returned. + * + * The computed key follows the specification described in RFC 5705. + * That RFC includes two key computations, with and without a "context + * value". If `context` is `NULL`, then the variant without context is + * used; otherwise, the `context_len` bytes located at the address + * pointed to by `context` are used in the computation. Note that it + * is possible to have a "with context" key with a context length of + * zero bytes, by setting `context` to a non-`NULL` value but + * `context_len` to 0. + * + * When context bytes are used, the context length MUST NOT exceed + * 65535 bytes. + * + * \param cc SSL engine context. + * \param dst destination buffer for exported key. + * \param len exported key length (in bytes). + * \param label disambiguation label. + * \param context context value (or `NULL`). + * \param context_len context length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len); + +/* + * Pre-declaration for the SSL client context. + */ +typedef struct br_ssl_client_context_ br_ssl_client_context; + +/** + * \brief Type for the client certificate, if requested by the server. + */ +typedef struct { + /** + * \brief Authentication type. + * + * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` + * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). + */ + int auth_type; + + /** + * \brief Hash function for computing the CertificateVerify. + * + * This is the symbolic identifier for the hash function that + * will be used to produce the hash of handshake messages, to + * be signed into the CertificateVerify. For full static ECDH + * (client and server certificates are both EC in the same + * curve, and static ECDH is used), this value is set to -1. + * + * Take care that with TLS 1.0 and 1.1, that value MUST match + * the protocol requirements: value must be 0 (MD5+SHA-1) for + * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only + * TLS 1.2 allows for other hash functions. + */ + int hash_id; + + /** + * \brief Certificate chain to send to the server. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The client + * code does not try to decode these elements. If there is no + * chain to send to the server, then this pointer shall be + * set to `NULL`. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + * + * If there is no chain to send to the server, then this value + * shall be set to 0. + */ + size_t chain_len; + +} br_ssl_client_certificate; + +/* + * Note: the constants below for signatures match the TLS constants. + */ + +/** \brief Client authentication type: static ECDH. */ +#define BR_AUTH_ECDH 0 +/** \brief Client authentication type: RSA signature. */ +#define BR_AUTH_RSA 1 +/** \brief Client authentication type: ECDSA signature. */ +#define BR_AUTH_ECDSA 3 + +/** + * \brief Class type for a certificate handler (client side). + * + * A certificate handler selects a client certificate chain to send to + * the server, upon explicit request from that server. It receives + * the list of trust anchor DN from the server, and supported types + * of certificates and signatures, and returns the chain to use. It + * is also invoked to perform the corresponding private key operation + * (a signature, or an ECDH computation). + * + * The SSL client engine will first push the trust anchor DN with + * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` + * and `end_name_list()`. Then it will call `choose()`, to select the + * actual chain (and signature/hash algorithms). Finally, it will call + * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. + */ +typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; +struct br_ssl_client_certificate_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Begin reception of a list of trust anchor names. This + * is called while parsing the incoming CertificateRequest. + * + * \param pctx certificate handler context. + */ + void (*start_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Begin reception of a new trust anchor name. + * + * The total encoded name length is provided; it is less than + * 65535 bytes. + * + * \param pctx certificate handler context. + * \param len encoded name length (in bytes). + */ + void (*start_name)(const br_ssl_client_certificate_class **pctx, + size_t len); + + /** + * \brief Receive some more bytes for the current trust anchor name. + * + * The provided reference (`data`) points to a transient buffer + * they may be reused as soon as this function returns. The chunk + * length (`len`) is never zero. + * + * \param pctx certificate handler context. + * \param data anchor name chunk. + * \param len anchor name chunk length (in bytes). + */ + void (*append_name)(const br_ssl_client_certificate_class **pctx, + const unsigned char *data, size_t len); + + /** + * \brief End current trust anchor name. + * + * This function is called when all the encoded anchor name data + * has been provided. + * + * \param pctx certificate handler context. + */ + void (*end_name)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief End list of trust anchor names. + * + * This function is called when all the anchor names in the + * CertificateRequest message have been obtained. + * + * \param pctx certificate handler context. + */ + void (*end_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Select client certificate and algorithms. + * + * This callback function shall fill the provided `choices` + * structure with the selected algorithms and certificate chain. + * The `hash_id`, `chain` and `chain_len` fields must be set. If + * the client cannot or does not wish to send a certificate, + * then it shall set `chain` to `NULL` and `chain_len` to 0. + * + * The `auth_types` parameter describes the authentication types, + * signature algorithms and hash functions that are supported by + * both the client context and the server, and compatible with + * the current protocol version. This is a bit field with the + * following contents: + * + * - If RSA signatures with hash function x are supported, then + * bit x is set. + * + * - If ECDSA signatures with hash function x are supported, + * then bit 8+x is set. + * + * - If static ECDH is supported, with a RSA-signed certificate, + * then bit 16 is set. + * + * - If static ECDH is supported, with an ECDSA-signed certificate, + * then bit 17 is set. + * + * Notes: + * + * - When using TLS 1.0 or 1.1, the hash function for RSA + * signatures is always the special MD5+SHA-1 (id 0), and the + * hash function for ECDSA signatures is always SHA-1 (id 2). + * + * - When using TLS 1.2, the list of hash functions is trimmed + * down to include only hash functions that the client context + * can support. The actual server list can be obtained with + * `br_ssl_client_get_server_hashes()`; that list may be used + * to select the certificate chain to send to the server. + * + * \param pctx certificate handler context. + * \param cc SSL client context. + * \param auth_types supported authentication types and algorithms. + * \param choices destination structure for the policy choices. + */ + void (*choose)(const br_ssl_client_certificate_class **pctx, + const br_ssl_client_context *cc, uint32_t auth_types, + br_ssl_client_certificate *choices); + + /** + * \brief Perform key exchange (client part). + * + * This callback is invoked in case of a full static ECDH key + * exchange: + * + * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; + * + * - the server requests a client certificate; + * + * - the client has, and sends, a client certificate that + * uses an EC key in the same curve as the server's key, + * and chooses static ECDH (the `hash_id` field in the choice + * structure was set to -1). + * + * In that situation, this callback is invoked to compute the + * client-side ECDH: the provided `data` (of length `*len` bytes) + * is the server's public key point (as decoded from its + * certificate), and the client shall multiply that point with + * its own private key, and write back the X coordinate of the + * resulting point in the same buffer, starting at offset 0. + * The `*len` value shall be modified to designate the actual + * length of the X coordinate. + * + * The callback must uphold the following: + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx certificate handler context. + * \param data server public key point. + * \param len public key point length / X coordinate length. + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (client authentication). + * + * This callback is invoked when a client certificate was sent, + * and static ECDH is not used. It shall compute a signature, + * using the client's private key, over the provided hash value + * (which is the hash of all previous handshake messages). + * + * On input, the hash value to sign is in `data`, of size + * `hv_len`; the involved hash function is identified by + * `hash_id`. The signature shall be computed and written + * back into `data`; the total size of that buffer is `len` + * bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * For RSA signatures, the `hash_id` may be 0, in which case + * this is the special header-less signature specified in TLS 1.0 + * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 + * v1.5 signatures shall be computed. + * + * For ECDSA signatures, the signature value shall use the ASN.1 + * based encoding. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx certificate handler context. + * \param hash_id hash function identifier. + * \param hv_len hash value length (in bytes). + * \param data input/output buffer (hash value, then signature). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len); +}; + +/** + * \brief A single-chain RSA client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_client_certificate_rsa_context; + +/** + * \brief A single-chain EC client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * This handler may support both static ECDH, and ECDSA signatures + * (either usage may be selectively disabled). + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_client_certificate_ec_context; + +/** + * \brief Context structure for a SSL client. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_client_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Minimum ClientHello length; padding with an extension (RFC + * 7685) is added if necessary to match at least that length. + * Such padding is nominally unnecessary, but it has been used + * to work around some server implementation bugs. + */ + uint16_t min_clienthello_len; + + /* + * Bit field for algoithms (hash + signature) supported by the + * server when requesting a client certificate. + */ + uint32_t hashes; + + /* + * Server's public key curve. + */ + int server_curve; + + /* + * Context for certificate handler. + */ + const br_ssl_client_certificate_class **client_auth_vtable; + + /* + * Client authentication type. + */ + unsigned char auth_type; + + /* + * Hash function to use for the client signature. This is 0xFF + * if static ECDH is used. + */ + unsigned char hash_id; + + /* + * For the core certificate handlers, thus avoiding (in most + * cases) the need for an externally provided policy context. + */ + union { + const br_ssl_client_certificate_class *vtable; + br_ssl_client_certificate_rsa_context single_rsa; + br_ssl_client_certificate_ec_context single_ec; + } client_auth; + + /* + * Implementations. + */ + br_rsa_public irsapub; +#endif +}; + +/** + * \brief Get the hash functions and signature algorithms supported by + * the server. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc client context. + * \return the server-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the server key curve. + * + * This function returns the ID for the curve used by the server's public + * key. This is set when the server's certificate chain is processed; + * this value is 0 if the server's key is not an EC key. + * + * \return the server's public key curve ID, or 0. + */ +static inline int +br_ssl_client_get_server_curve(const br_ssl_client_context *cc) +{ + return cc->server_curve; +} + +/* + * Each br_ssl_client_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full all supported versions and suites; constant-time implementations + * TODO: add other profiles + */ + +/** + * \brief SSL client profile: full. + * + * This function initialises the provided SSL client context with + * all supported algorithms and cipher suites. It also initialises + * a companion X.509 validation engine with all supported algorithms, + * and the provided trust anchors; the X.509 engine will be used by + * the client context to validate the server's certificate. + * + * \param cc client context to initialise. + * \param xc X.509 validation context to initialise. + * \param trust_anchors trust anchors to use. + * \param trust_anchors_num number of trust anchors. + */ +void br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Clear the complete contents of a SSL client context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc client context to clear. + */ +void br_ssl_client_zero(br_ssl_client_context *cc); + +/** + * \brief Set an externally provided client certificate handler context. + * + * The handler's methods are invoked when the server requests a client + * certificate. + * + * \param cc client context. + * \param pctx certificate handler context (pointer to its vtable field). + */ +static inline void +br_ssl_client_set_client_certificate(br_ssl_client_context *cc, + const br_ssl_client_certificate_class **pctx) +{ + cc->client_auth_vtable = pctx; +} + +/** + * \brief Set the RSA public-key operations implementation. + * + * This will be used to encrypt the pre-master secret with the server's + * RSA public key (RSA-encryption cipher suites only). + * + * \param cc client context. + * \param irsapub RSA public-key encryption implementation. + */ +static inline void +br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) +{ + cc->irsapub = irsapub; +} + +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + +/** + * \brief Set the minimum ClientHello length (RFC 7685 padding). + * + * If this value is set and the ClientHello would be shorter, then + * the Pad ClientHello extension will be added with enough padding bytes + * to reach the target size. Because of the extension header, the resulting + * size will sometimes be slightly more than `len` bytes if the target + * size cannot be exactly met. + * + * The target length relates to the _contents_ of the ClientHello, not + * counting its 4-byte header. For instance, if `len` is set to 512, + * then the padding will bring the ClientHello size to 516 bytes with its + * header, and 521 bytes when counting the 5-byte record header. + * + * \param cc client context. + * \param len minimum ClientHello length (in bytes). + */ +static inline void +br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) +{ + cc->min_clienthello_len = len; +} + +/** + * \brief Prepare or reset a client context for a new connection. + * + * The `server_name` parameter is used to fill the SNI extension; the + * X.509 "minimal" engine will also match that name against the server + * names included in the server's certificate. If the parameter is + * `NULL` then no SNI extension will be sent, and the X.509 "minimal" + * engine (if used for server certificate validation) will not check + * presence of any specific name in the received certificate. + * + * Therefore, setting the `server_name` to `NULL` shall be reserved + * to cases where alternate or additional methods are used to ascertain + * that the right server public key is used (e.g. a "known key" model). + * + * If `resume_session` is non-zero and the context was previously used + * then the session parameters may be reused (depending on whether the + * server previously sent a non-empty session ID, and accepts the session + * resumption). The session parameters for session resumption can also + * be set explicitly with `br_ssl_engine_set_session_parameters()`. + * + * On failure, the context is marked as failed, and this function + * returns 0. A possible failure condition is when no initial entropy + * was injected, and none could be obtained from the OS (either OS + * randomness gathering is not supported, or it failed). + * + * \param cc client context. + * \param server_name target server name, or `NULL`. + * \param resume_session non-zero to try session resumption. + * \return 0 on failure, 1 on success. + */ +int br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session); + +/** + * \brief Forget any session in the context. + * + * This means that the next handshake that uses this context will + * necessarily be a full handshake (this applies both to new connections + * and to renegotiations). + * + * \param cc client context. + */ +static inline void +br_ssl_client_forget_session(br_ssl_client_context *cc) +{ + cc->eng.session.session_id_len = 0; +} + +/** + * \brief Set client certificate chain and key (single RSA case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an RSA public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * \param cc SSL client context. + * \param chain client certificate chain (SSL order: EE comes first). + * \param chain_len client chain length (number of certificates). + * \param sk client private key. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); + +/* + * \brief Set the client certificate chain and key (single EC case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an EC public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` + * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value + * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA + * signature implementation must be provided; otherwise, the `iecdsa` + * parameter may be 0. + * + * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or + * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA + * that issued (signed) the client certificate. That value is used with + * full static ECDH: support of the certificate by the server depends + * on how the certificate was signed. (Note: when using TLS 1.2, this + * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Type for a "translated cipher suite", as an array of two + * 16-bit integers. + * + * The first element is the cipher suite identifier (as used on the wire). + * The second element is the concatenation of four 4-bit elements which + * characterise the cipher suite contents. In most to least significant + * order, these 4-bit elements are: + * + * - Bits 12 to 15: key exchange + server key type + * + * | val | symbolic constant | suite type | details | + * | :-- | :----------------------- | :---------- | :----------------------------------------------- | + * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | + * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | + * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | + * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | + * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | + * + * - Bits 8 to 11: symmetric encryption algorithm + * + * | val | symbolic constant | symmetric encryption | key strength (bits) | + * | :-- | :--------------------- | :------------------- | :------------------ | + * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | + * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | + * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | + * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | + * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | + * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | + * + * - Bits 4 to 7: MAC algorithm + * + * | val | symbolic constant | MAC type | details | + * | :-- | :----------------- | :----------- | :------------------------------------ | + * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | + * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | + * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | + * + * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 + * + * | val | symbolic constant | hash function | details | + * | :-- | :----------------- | :------------ | :----------------------------------- | + * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | + * + * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has + * standard identifier 0x009C, and is translated to 0x0304, for, in + * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), + * SHA-256 in the TLS PRF (4). + */ +typedef uint16_t br_suite_translated[2]; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Constants are already documented in the br_suite_translated type. + */ + +#define BR_SSLKEYX_RSA 0 +#define BR_SSLKEYX_ECDHE_RSA 1 +#define BR_SSLKEYX_ECDHE_ECDSA 2 +#define BR_SSLKEYX_ECDH_RSA 3 +#define BR_SSLKEYX_ECDH_ECDSA 4 + +#define BR_SSLENC_3DES_CBC 0 +#define BR_SSLENC_AES128_CBC 1 +#define BR_SSLENC_AES256_CBC 2 +#define BR_SSLENC_AES128_GCM 3 +#define BR_SSLENC_AES256_GCM 4 +#define BR_SSLENC_CHACHA20 5 + +#define BR_SSLMAC_AEAD 0 +#define BR_SSLMAC_SHA1 br_sha1_ID +#define BR_SSLMAC_SHA256 br_sha256_ID +#define BR_SSLMAC_SHA384 br_sha384_ID + +#define BR_SSLPRF_SHA256 br_sha256_ID +#define BR_SSLPRF_SHA384 br_sha384_ID + +#endif + +/* + * Pre-declaration for the SSL server context. + */ +typedef struct br_ssl_server_context_ br_ssl_server_context; + +/** + * \brief Type for the server policy choices, taken after analysis of + * the client message (ClientHello). + */ +typedef struct { + /** + * \brief Cipher suite to use with that client. + */ + uint16_t cipher_suite; + + /** + * \brief Hash function or algorithm for signing the ServerKeyExchange. + * + * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` + * cipher suites; it is used only for `TLS_ECDHE_*` suites, in + * which the server _signs_ the ephemeral EC Diffie-Hellman + * parameters sent to the client. + * + * This identifier must be one of the following values: + * + * - `0xFF00 + id`, where `id` is a hash function identifier + * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); + * + * - a full 16-bit identifier, lower than `0xFF00`. + * + * If the first option is used, then the SSL engine will + * compute the hash of the data that is to be signed, with the + * designated hash function. The `do_sign()` method will be + * invoked with that hash value provided in the the `data` + * buffer. + * + * If the second option is used, then the SSL engine will NOT + * compute a hash on the data; instead, it will provide the + * to-be-signed data itself in `data`, i.e. the concatenation of + * the client random, server random, and encoded ECDH + * parameters. Furthermore, with TLS-1.2 and later, the 16-bit + * identifier will be used "as is" in the protocol, in the + * SignatureAndHashAlgorithm; for instance, `0x0401` stands for + * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash + * function (the `04`). + * + * Take care that with TLS 1.0 and 1.1, the hash function is + * constrainted by the protocol: RSA signature must use + * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 + * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a + * SignatureAndHashAlgorithm field in their ServerKeyExchange + * messages, any value below `0xFF00` will be usable to send the + * raw ServerKeyExchange data to the `do_sign()` callback, but + * that callback must still follow the protocol requirements + * when generating the signature. + */ + unsigned algo_id; + + /** + * \brief Certificate chain to send to the client. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The server + * code does not try to decode these elements. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + */ + size_t chain_len; + +} br_ssl_server_choices; + +/** + * \brief Class type for a policy handler (server side). + * + * A policy handler selects the policy parameters for a connection + * (cipher suite and other algorithms, and certificate chain to send to + * the client); it also performs the server-side computations involving + * its permanent private key. + * + * The SSL server engine will invoke first `choose()`, once the + * ClientHello message has been received, then either `do_keyx()` + * `do_sign()`, depending on the cipher suite. + */ +typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; +struct br_ssl_server_policy_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Select algorithms and certificates for this connection. + * + * This callback function shall fill the provided `choices` + * structure with the policy choices for this connection. This + * entails selecting the cipher suite, hash function for signing + * the ServerKeyExchange (applicable only to ECDHE cipher suites), + * and certificate chain to send. + * + * The callback receives a pointer to the server context that + * contains the relevant data. In particular, the functions + * `br_ssl_server_get_client_suites()`, + * `br_ssl_server_get_client_hashes()` and + * `br_ssl_server_get_client_curves()` can be used to obtain + * the cipher suites, hash functions and elliptic curves + * supported by both the client and server, respectively. The + * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` + * functions yield the protocol version and requested server name + * (SNI), respectively. + * + * This function may modify its context structure (`pctx`) in + * arbitrary ways to keep track of its own choices. + * + * This function shall return 1 if appropriate policy choices + * could be made, or 0 if this connection cannot be pursued. + * + * \param pctx policy context. + * \param cc SSL server context. + * \param choices destination structure for the policy choices. + * \return 1 on success, 0 on error. + */ + int (*choose)(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices); + + /** + * \brief Perform key exchange (server part). + * + * This callback is invoked to perform the server-side cryptographic + * operation for a key exchange that is not ECDHE. This callback + * uses the private key. + * + * **For RSA key exchange**, the provided `data` (of length `*len` + * bytes) shall be decrypted with the server's private key, and + * the 48-byte premaster secret copied back to the first 48 bytes + * of `data`. + * + * - The caller makes sure that `*len` is at least 59 bytes. + * + * - This callback MUST check that the provided length matches + * that of the key modulus; it shall report an error otherwise. + * + * - If the length matches that of the RSA key modulus, then + * processing MUST be constant-time, even if decryption fails, + * or the padding is incorrect, or the plaintext message length + * is not exactly 48 bytes. + * + * - This callback needs not check the two first bytes of the + * obtained pre-master secret (the caller will do that). + * + * - If an error is reported (0), then what the callback put + * in the first 48 bytes of `data` is unimportant (the caller + * will use random bytes instead). + * + * **For ECDH key exchange**, the provided `data` (of length `*len` + * bytes) is the elliptic curve point from the client. The + * callback shall multiply it with its private key, and store + * the resulting X coordinate in `data`, starting at offset 0, + * and set `*len` to the length of the X coordinate. + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx policy context. + * \param data key exchange data from the client. + * \param len key exchange data length (in bytes). + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (for a ServerKeyExchange message). + * + * This callback function is invoked for ECDHE cipher suites. On + * input, the hash value or message to sign is in `data`, of + * size `hv_len`; the involved hash function or algorithm is + * identified by `algo_id`. The signature shall be computed and + * written back into `data`; the total size of that buffer is + * `len` bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * The `algo_id` value matches that which was written in the + * `choices` structures by the `choose()` callback. This will be + * one of the following: + * + * - `0xFF00 + id` for a hash function identifier `id`. In + * that case, the `data` buffer contains a hash value + * already computed over the data that is to be signed, + * of length `hv_len`. The `id` may be 0 to designate the + * special MD5+SHA-1 concatenation (old-style RSA signing). + * + * - Another value, lower than `0xFF00`. The `data` buffer + * then contains the raw, non-hashed data to be signed + * (concatenation of the client and server randoms and + * ECDH parameters). The callback is responsible to apply + * any relevant hashing as part of the signing process. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx policy context. + * \param algo_id hash function / algorithm identifier. + * \param data input/output buffer (message/hash, then signature). + * \param hv_len hash value or message length (in bytes). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_server_policy_class **pctx, + unsigned algo_id, + unsigned char *data, size_t hv_len, size_t len); +}; + +/** + * \brief A single-chain RSA policy handler. + * + * This policy context uses a single certificate chain, and a RSA + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + unsigned allowed_usages; + br_rsa_private irsacore; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_server_policy_rsa_context; + +/** + * \brief A single-chain EC policy handler. + * + * This policy context uses a single certificate chain, and an EC + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Due to how TLS is defined, this context must be made aware whether + * the server certificate was itself signed with RSA or ECDSA. The code + * does not try to decode the certificate to obtain that information. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned cert_issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_server_policy_ec_context; + +/** + * \brief Class type for a session parameter cache. + * + * Session parameters are saved in the cache with `save()`, and + * retrieved with `load()`. The cache implementation can apply any + * storage and eviction strategy that it sees fit. The SSL server + * context that performs the request is provided, so that its + * functionalities may be used by the implementation (e.g. hash + * functions or random number generation). + */ +typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; +struct br_ssl_session_cache_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Record a session. + * + * This callback should record the provided session parameters. + * The `params` structure is transient, so its contents shall + * be copied into the cache. The session ID has been randomly + * generated and always has length exactly 32 bytes. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params session parameters to save. + */ + void (*save)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params); + + /** + * \brief Lookup a session in the cache. + * + * The session ID to lookup is in `params` and always has length + * exactly 32 bytes. If the session parameters are found in the + * cache, then the parameters shall be copied into the `params` + * structure. Returned value is 1 on successful lookup, 0 + * otherwise. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params destination for session parameters. + * \return 1 if found, 0 otherwise. + */ + int (*load)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params); +}; + +/** + * \brief Context for a basic cache system. + * + * The system stores session parameters in a buffer provided at + * initialisation time. Each entry uses exactly 100 bytes, and + * buffer sizes up to 4294967295 bytes are supported. + * + * Entries are evicted with a LRU (Least Recently Used) policy. A + * search tree is maintained to keep lookups fast even with large + * caches. + * + * Apart from the first field (vtable pointer), the structure + * contents are opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_session_cache_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char *store; + size_t store_len, store_ptr; + unsigned char index_key[32]; + const br_hash_class *hash; + int init_done; + uint32_t head, tail, root; +#endif +} br_ssl_session_cache_lru; + +/** + * \brief Initialise a LRU session cache with the provided storage space. + * + * The provided storage space must remain valid as long as the cache + * is used. Arbitrary lengths are supported, up to 4294967295 bytes; + * each entry uses up exactly 100 bytes. + * + * \param cc session cache context. + * \param store storage space for cached entries. + * \param store_len storage space length (in bytes). + */ +void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len); + +/** + * \brief Forget an entry in an LRU session cache. + * + * The session cache context must have been initialised. The entry + * with the provided session ID (of exactly 32 bytes) is looked for + * in the cache; if located, it is disabled. + * + * \param cc session cache context. + * \param id session ID to forget. + */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id); + +/** + * \brief Context structure for a SSL server. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_server_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Maximum version from the client. + */ + uint16_t client_max_version; + + /* + * Session cache. + */ + const br_ssl_session_cache_class **cache_vtable; + + /* + * Translated cipher suites supported by the client. The list + * is trimmed to include only the cipher suites that the + * server also supports; they are in the same order as in the + * client message. + */ + br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; + unsigned char client_suites_num; + + /* + * Hash functions supported by the client, with ECDSA and RSA + * (bit mask). For hash function with id 'x', set bit index is + * x for RSA, x+8 for ECDSA. For newer algorithms, with ID + * 0x08**, bit 16+k is set for algorithm 0x0800+k. + */ + uint32_t hashes; + + /* + * Curves supported by the client (bit mask, for named curves). + */ + uint32_t curves; + + /* + * Context for chain handler. + */ + const br_ssl_server_policy_class **policy_vtable; + uint16_t sign_hash_id; + + /* + * For the core handlers, thus avoiding (in most cases) the + * need for an externally provided policy context. + */ + union { + const br_ssl_server_policy_class *vtable; + br_ssl_server_policy_rsa_context single_rsa; + br_ssl_server_policy_ec_context single_ec; + } chain_handler; + + /* + * Buffer for the ECDHE private key. + */ + unsigned char ecdhe_key[70]; + size_t ecdhe_key_len; + + /* + * Trust anchor names for client authentication. "ta_names" and + * "tas" cannot be both non-NULL. + */ + const br_x500_name *ta_names; + const br_x509_trust_anchor *tas; + size_t num_tas; + size_t cur_dn_index; + const unsigned char *cur_dn; + size_t cur_dn_len; + + /* + * Buffer for the hash value computed over all handshake messages + * prior to CertificateVerify, and identifier for the hash function. + */ + unsigned char hash_CV[64]; + size_t hash_CV_len; + int hash_CV_id; + + /* + * Server-specific implementations. + * (none for now) + */ +#endif +}; + +/* + * Each br_ssl_server_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full_rsa all supported algorithm, server key type is RSA + * full_ec all supported algorithm, server key type is EC + * TODO: add other profiles + * + * Naming scheme for "minimal" profiles: min123 + * + * -- character 1: key exchange + * r = RSA + * e = ECDHE_RSA + * f = ECDHE_ECDSA + * u = ECDH_RSA + * v = ECDH_ECDSA + * -- character 2: version / PRF + * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 + * 2 = TLS 1.2 with SHA-256 + * 3 = TLS 1.2 with SHA-384 + * -- character 3: encryption + * a = AES/CBC + * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 + */ + +/** + * \brief SSL server profile: full_rsa. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on a RSA + * key pair. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: full_ec. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on an EC + * key pair. + * + * The key type of the CA that issued the server's certificate must + * be provided, since it matters for ECDH cipher suites (ECDH_RSA + * suites require a RSA-powered CA). The key type is either + * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len chain length (number of certificates). + * \param cert_issuer_key_type certificate issuer's key type. + * \param sk EC private key. + */ +void br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minr2g. + * + * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is + * RSA, and RSA key exchange is used (not forward secure, but uses little + * CPU in the client). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: mine2g. + * + * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key + * is RSA, and ECDHE key exchange is used. This suite provides forward + * security, with a higher CPU expense on the client, and a somewhat + * larger code footprint (compared to "minr2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2g. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security, with a higher CPU expense on the client and server + * (by a factor of about 3 to 4), and a somewhat larger code footprint + * (compared to "minu2g" and "minv2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minu2g. + * + * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * a RSA key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minv2g. + * + * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * an EC key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: mine2c. + * + * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is RSA, and ECDHE key exchange is used. This suite + * provides forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2c. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief Get the supported client suites. + * + * This function shall be called only after the ClientHello has been + * processed, typically from the policy engine. The returned array + * contains the cipher suites that are supported by both the client + * and the server; these suites are in client preference order, unless + * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case + * they are in server preference order. + * + * The suites are _translated_, which means that each suite is given + * as two 16-bit integers: the standard suite identifier, and its + * translated version, broken down into its individual components, + * as explained with the `br_suite_translated` type. + * + * The returned array is allocated in the context and will be rewritten + * by each handshake. + * + * \param cc server context. + * \param num receives the array size (number of suites). + * \return the translated common cipher suites, in preference order. + */ +static inline const br_suite_translated * +br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) +{ + *num = cc->client_suites_num; + return cc->client_suites; +} + +/** + * \brief Get the hash functions and signature algorithms supported by + * the client. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc server context. + * \return the client-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the elliptic curves supported by the client. + * + * This is a bit field (bit x is set if curve of ID x is supported). + * + * \param cc server context. + * \return the client-supported elliptic curves. + */ +static inline uint32_t +br_ssl_server_get_client_curves(const br_ssl_server_context *cc) +{ + return cc->curves; +} + +/** + * \brief Clear the complete contents of a SSL server context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc server context to clear. + */ +void br_ssl_server_zero(br_ssl_server_context *cc); + +/** + * \brief Set an externally provided policy context. + * + * The policy context's methods are invoked to decide the cipher suite + * and certificate chain, and to perform operations involving the server's + * private key. + * + * \param cc server context. + * \param pctx policy context (pointer to its vtable field). + */ +static inline void +br_ssl_server_set_policy(br_ssl_server_context *cc, + const br_ssl_server_policy_class **pctx) +{ + cc->policy_vtable = pctx; +} + +/** + * \brief Set the server certificate chain and key (single RSA case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with a RSA + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for + * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). + * + * \param cc server context. + * \param chain server certificate chain to send to the client. + * \param chain_len chain length (number of certificates). + * \param sk server private key (RSA). + * \param allowed_usages allowed private key usages. + * \param irsacore RSA core implementation. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); + +/** + * \brief Set the server certificate chain and key (single EC case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with an EC + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for + * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). + * + * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), + * the algorithm type of the key used by the issuing CA to sign the + * server's certificate must be provided, as `cert_issuer_key_type` + * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_server_set_single_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Activate client certificate authentication. + * + * The trust anchor encoded X.500 names (DN) to send to the client are + * provided. A client certificate will be requested and validated through + * the X.509 validator configured in the SSL engine. If `num` is 0, then + * client certificate authentication is disabled. + * + * If the client does not send a certificate, or on validation failure, + * the handshake aborts. Unauthenticated clients can be tolerated by + * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param ta_names encoded trust anchor names. + * \param num number of encoded trust anchor names. + */ +static inline void +br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, + const br_x500_name *ta_names, size_t num) +{ + cc->ta_names = ta_names; + cc->tas = NULL; + cc->num_tas = num; +} + +/** + * \brief Activate client certificate authentication. + * + * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the + * trust anchor names are provided not as an array of stand-alone names + * (`br_x500_name` structures), but as an array of trust anchors + * (`br_x509_trust_anchor` structures). The server engine itself will + * only use the `dn` field of each trust anchor. This is meant to allow + * defining a single array of trust anchors, to be used here and in the + * X.509 validation engine itself. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param tas trust anchors (only names are used). + * \param num number of trust anchors. + */ +static inline void +br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, + const br_x509_trust_anchor *tas, size_t num) +{ + cc->ta_names = NULL; + cc->tas = tas; + cc->num_tas = num; +} + +/** + * \brief Configure the cache for session parameters. + * + * The cache context is provided as a pointer to its first field (vtable + * pointer). + * + * \param cc server context. + * \param vtable session cache context. + */ +static inline void +br_ssl_server_set_cache(br_ssl_server_context *cc, + const br_ssl_session_cache_class **vtable) +{ + cc->cache_vtable = vtable; +} + +/** + * \brief Prepare or reset a server context for handling an incoming client. + * + * \param cc server context. + * \return 1 on success, 0 on error. + */ +int br_ssl_server_reset(br_ssl_server_context *cc); + +/* ===================================================================== */ + +/* + * Context for the simplified I/O context. The transport medium is accessed + * through the low_read() and low_write() callback functions, each with + * its own opaque context pointer. + * + * low_read() read some bytes, at most 'len' bytes, into data[]. The + * returned value is the number of read bytes, or -1 on error. + * The 'len' parameter is guaranteed never to exceed 20000, + * so the length always fits in an 'int' on all platforms. + * + * low_write() write up to 'len' bytes, to be read from data[]. The + * returned value is the number of written bytes, or -1 on + * error. The 'len' parameter is guaranteed never to exceed + * 20000, so the length always fits in an 'int' on all + * parameters. + * + * A socket closure (if the transport medium is a socket) should be reported + * as an error (-1). The callbacks shall endeavour to block until at least + * one byte can be read or written; a callback returning 0 at times is + * acceptable, but this normally leads to the callback being immediately + * called again, so the callback should at least always try to block for + * some time if no I/O can take place. + * + * The SSL engine naturally applies some buffering, so the callbacks need + * not apply buffers of their own. + */ +/** + * \brief Context structure for the simplified SSL I/O wrapper. + * + * This structure is initialised with `br_sslio_init()`. Its contents + * are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_ssl_engine_context *engine; + int (*low_read)(void *read_context, + unsigned char *data, size_t len); + void *read_context; + int (*low_write)(void *write_context, + const unsigned char *data, size_t len); + void *write_context; +#endif +} br_sslio_context; + +/** + * \brief Initialise a simplified I/O wrapper context. + * + * The simplified I/O wrapper offers a simpler read/write API for a SSL + * engine (client or server), using the provided callback functions for + * reading data from, or writing data to, the transport medium. + * + * The callback functions have the following semantics: + * + * - Each callback receives an opaque context value (of type `void *`) + * that the callback may use arbitrarily (or possibly ignore). + * + * - `low_read()` reads at least one byte, at most `len` bytes, from + * the transport medium. Read bytes shall be written in `data`. + * + * - `low_write()` writes at least one byte, at most `len` bytes, unto + * the transport medium. The bytes to write are read from `data`. + * + * - The `len` parameter is never zero, and is always lower than 20000. + * + * - The number of processed bytes (read or written) is returned. Since + * that number is less than 20000, it always fits on an `int`. + * + * - On error, the callbacks return -1. Reaching end-of-stream is an + * error. Errors are permanent: the SSL connection is terminated. + * + * - Callbacks SHOULD NOT return 0. This is tolerated, as long as + * callbacks endeavour to block for some non-negligible amount of + * time until at least one byte can be sent or received (if a + * callback returns 0, then the wrapper invokes it again + * immediately). + * + * - Callbacks MAY return as soon as at least one byte is processed; + * they MAY also insist on reading or writing _all_ requested bytes. + * Since SSL is a self-terminated protocol (each record has a length + * header), this does not change semantics. + * + * - Callbacks need not apply any buffering (for performance) since SSL + * itself uses buffers. + * + * \param ctx wrapper context to initialise. + * \param engine SSL engine to wrap. + * \param low_read callback for reading data from the transport. + * \param read_context context pointer for `low_read()`. + * \param low_write callback for writing data on the transport. + * \param write_context context pointer for `low_write()`. + */ +void br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context); + +/** + * \brief Read some application data from a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been obtained. + * Returned value is the number of bytes read, or -1 on error. The + * number of bytes always fits on an 'int' (data from a single SSL/TLS + * record is returned). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len maximum number of bytes to obtain. + * \return number of bytes obtained, or -1 on error. + */ +int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Read application data from a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes are read, + * or an error is reached. Returned value is 0 on success, -1 on error. + * A normal (verified) SSL closure before that many bytes are obtained + * is reported as an error by this function. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len number of bytes to obtain. + * \return 0 on success, or -1 on error. + */ +int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Write some application data unto a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been written. + * Returned value is the number of bytes written, or -1 on error. The + * number of bytes always fits on an 'int' (less than 20000). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len maximum number of bytes to write. + * \return number of bytes written, or -1 on error. + */ +int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Write application data unto a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes have been + * written, or an error is reached. Returned value is 0 on success, -1 + * on error. A normal (verified) SSL closure before that many bytes are + * written is reported as an error by this function. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len number of bytes to write. + * \return 0 on success, or -1 on error. + */ +int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Flush pending data. + * + * This call makes sure that any buffered application data in the + * provided context (including the wrapped SSL engine) has been sent + * to the transport medium (i.e. accepted by the `low_write()` callback + * method). If there is no such pending data, then this function does + * nothing (and returns a success, i.e. 0). + * + * If the underlying transport medium has its own buffers, then it is + * up to the caller to ensure the corresponding flushing. + * + * Returned value is 0 on success, -1 on error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_flush(br_sslio_context *cc); + +/** + * \brief Close the SSL connection. + * + * This call runs the SSL closure protocol (sending a `close_notify`, + * receiving the response `close_notify`). When it returns, the SSL + * connection is finished. It is still up to the caller to manage the + * possible transport-level termination, if applicable (alternatively, + * the underlying transport stream may be reused for non-SSL messages). + * + * Returned value is 0 on success, -1 on error. A failure by the peer + * to process the complete closure protocol (i.e. sending back the + * `close_notify`) is an error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_close(br_sslio_context *cc); + +/* ===================================================================== */ + +/* + * Symbolic constants for cipher suites. + */ + +/* From RFC 5246 */ +#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 +#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 +#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 +#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B +#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 +#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 +#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D +#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 +#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 +#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B +#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 +#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D + +/* From RFC 4492 */ +#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 +#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 +#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 +#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 +#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 +#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B +#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C +#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F +#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 +#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 +#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 +#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 +#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 + +/* From RFC 5288 */ +#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F +#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 +#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 +#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 +#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 +#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 +#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 +#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 +#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 + +/* From RFC 5289 */ +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E +#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 +#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 + +/* From RFC 6655 and 7251 */ +#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C +#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D +#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 +#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF + +/* From RFC 7905 */ +#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 +#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 +#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA +#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB +#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC +#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD +#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE + +/* From RFC 7507 */ +#define BR_TLS_FALLBACK_SCSV 0x5600 + +/* + * Symbolic constants for alerts. + */ +#define BR_ALERT_CLOSE_NOTIFY 0 +#define BR_ALERT_UNEXPECTED_MESSAGE 10 +#define BR_ALERT_BAD_RECORD_MAC 20 +#define BR_ALERT_RECORD_OVERFLOW 22 +#define BR_ALERT_DECOMPRESSION_FAILURE 30 +#define BR_ALERT_HANDSHAKE_FAILURE 40 +#define BR_ALERT_BAD_CERTIFICATE 42 +#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define BR_ALERT_CERTIFICATE_REVOKED 44 +#define BR_ALERT_CERTIFICATE_EXPIRED 45 +#define BR_ALERT_CERTIFICATE_UNKNOWN 46 +#define BR_ALERT_ILLEGAL_PARAMETER 47 +#define BR_ALERT_UNKNOWN_CA 48 +#define BR_ALERT_ACCESS_DENIED 49 +#define BR_ALERT_DECODE_ERROR 50 +#define BR_ALERT_DECRYPT_ERROR 51 +#define BR_ALERT_PROTOCOL_VERSION 70 +#define BR_ALERT_INSUFFICIENT_SECURITY 71 +#define BR_ALERT_INTERNAL_ERROR 80 +#define BR_ALERT_USER_CANCELED 90 +#define BR_ALERT_NO_RENEGOTIATION 100 +#define BR_ALERT_UNSUPPORTED_EXTENSION 110 +#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl/bearssl_x509.h b/template/sysroot/include/bearssl/bearssl_x509.h new file mode 100644 index 0000000..7668e1d --- /dev/null +++ b/template/sysroot/include/bearssl/bearssl_x509.h @@ -0,0 +1,1474 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_X509_H__ +#define BR_BEARSSL_X509_H__ + +#include +#include + +#include "bearssl_ec.h" +#include "bearssl_hash.h" +#include "bearssl_rsa.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_x509.h + * + * # X.509 Certificate Chain Processing + * + * An X.509 processing engine receives an X.509 chain, chunk by chunk, + * as received from a SSL/TLS client or server (the client receives the + * server's certificate chain, and the server receives the client's + * certificate chain if it requested a client certificate). The chain + * is thus injected in the engine in SSL order (end-entity first). + * + * The engine's job is to return the public key to use for SSL/TLS. + * How exactly that key is obtained and verified is entirely up to the + * engine. + * + * **The "known key" engine** returns a public key which is already known + * from out-of-band information (e.g. the client _remembers_ the key from + * a previous connection, as in the usual SSH model). This is the simplest + * engine since it simply ignores the chain, thereby avoiding the need + * for any decoding logic. + * + * **The "minimal" engine** implements minimal X.509 decoding and chain + * validation: + * + * - The provided chain should validate "as is". There is no attempt + * at reordering, skipping or downloading extra certificates. + * + * - X.509 v1, v2 and v3 certificates are supported. + * + * - Trust anchors are a DN and a public key. Each anchor is either a + * "CA" anchor, or a non-CA. + * + * - If the end-entity certificate matches a non-CA anchor (subject DN + * is equal to the non-CA name, and public key is also identical to + * the anchor key), then this is a _direct trust_ case and the + * remaining certificates are ignored. + * + * - Unless direct trust is applied, the chain must be verifiable up to + * a certificate whose issuer DN matches the DN from a "CA" trust anchor, + * and whose signature is verifiable against that anchor's public key. + * Subsequent certificates in the chain are ignored. + * + * - The engine verifies subject/issuer DN matching, and enforces + * processing of Basic Constraints and Key Usage extensions. The + * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name, + * Subject Directory Attribute, CRL Distribution Points, Freshest CRL, + * Authority Info Access and Subject Info Access extensions are + * ignored. The Subject Alt Name is decoded for the end-entity + * certificate under some conditions (see below). Other extensions + * are ignored if non-critical, or imply chain rejection if critical. + * + * - The Subject Alt Name extension is parsed for names of type `dNSName` + * when decoding the end-entity certificate, and only if there is a + * server name to match. If there is no SAN extension, then the + * Common Name from the subjectDN is used. That name matching is + * case-insensitive and honours a single starting wildcard (i.e. if + * the name in the certificate starts with "`*.`" then this matches + * any word as first element). Note: this name matching is performed + * also in the "direct trust" model. + * + * - DN matching is byte-to-byte equality (a future version might + * include some limited processing for case-insensitive matching and + * whitespace normalisation). + * + * - Successful validation produces a public key type but also a set + * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * The caller is responsible for checking that the key type and + * usages are compatible with the expected values (e.g. with the + * selected cipher suite, when the client validates the server's + * certificate). + * + * **Important caveats:** + * + * - The "minimal" engine does not check revocation status. The relevant + * extensions are ignored, and CRL or OCSP responses are not gathered + * or checked. + * + * - The "minimal" engine does not currently support Name Constraints + * (some basic functionality to handle sub-domains may be added in a + * later version). + * + * - The decoder is not "validating" in the sense that it won't reject + * some certificates with invalid field values when these fields are + * not actually processed. + */ + +/* + * X.509 error codes are in the 32..63 range. + */ + +/** \brief X.509 status: validation was successful; this is not actually + an error. */ +#define BR_ERR_X509_OK 32 + +/** \brief X.509 status: invalid value in an ASN.1 structure. */ +#define BR_ERR_X509_INVALID_VALUE 33 + +/** \brief X.509 status: truncated certificate. */ +#define BR_ERR_X509_TRUNCATED 34 + +/** \brief X.509 status: empty certificate chain (no certificate at all). */ +#define BR_ERR_X509_EMPTY_CHAIN 35 + +/** \brief X.509 status: decoding error: inner element extends beyond + outer element size. */ +#define BR_ERR_X509_INNER_TRUNC 36 + +/** \brief X.509 status: decoding error: unsupported tag class (application + or private). */ +#define BR_ERR_X509_BAD_TAG_CLASS 37 + +/** \brief X.509 status: decoding error: unsupported tag value. */ +#define BR_ERR_X509_BAD_TAG_VALUE 38 + +/** \brief X.509 status: decoding error: indefinite length. */ +#define BR_ERR_X509_INDEFINITE_LENGTH 39 + +/** \brief X.509 status: decoding error: extraneous element. */ +#define BR_ERR_X509_EXTRA_ELEMENT 40 + +/** \brief X.509 status: decoding error: unexpected element. */ +#define BR_ERR_X509_UNEXPECTED 41 + +/** \brief X.509 status: decoding error: expected constructed element, but + is primitive. */ +#define BR_ERR_X509_NOT_CONSTRUCTED 42 + +/** \brief X.509 status: decoding error: expected primitive element, but + is constructed. */ +#define BR_ERR_X509_NOT_PRIMITIVE 43 + +/** \brief X.509 status: decoding error: BIT STRING length is not multiple + of 8. */ +#define BR_ERR_X509_PARTIAL_BYTE 44 + +/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */ +#define BR_ERR_X509_BAD_BOOLEAN 45 + +/** \brief X.509 status: decoding error: value is off-limits. */ +#define BR_ERR_X509_OVERFLOW 46 + +/** \brief X.509 status: invalid distinguished name. */ +#define BR_ERR_X509_BAD_DN 47 + +/** \brief X.509 status: invalid date/time representation. */ +#define BR_ERR_X509_BAD_TIME 48 + +/** \brief X.509 status: certificate contains unsupported features that + cannot be ignored. */ +#define BR_ERR_X509_UNSUPPORTED 49 + +/** \brief X.509 status: key or signature size exceeds internal limits. */ +#define BR_ERR_X509_LIMIT_EXCEEDED 50 + +/** \brief X.509 status: key type does not match that which was expected. */ +#define BR_ERR_X509_WRONG_KEY_TYPE 51 + +/** \brief X.509 status: signature is invalid. */ +#define BR_ERR_X509_BAD_SIGNATURE 52 + +/** \brief X.509 status: validation time is unknown. */ +#define BR_ERR_X509_TIME_UNKNOWN 53 + +/** \brief X.509 status: certificate is expired or not yet valid. */ +#define BR_ERR_X509_EXPIRED 54 + +/** \brief X.509 status: issuer/subject DN mismatch in the chain. */ +#define BR_ERR_X509_DN_MISMATCH 55 + +/** \brief X.509 status: expected server name was not found in the chain. */ +#define BR_ERR_X509_BAD_SERVER_NAME 56 + +/** \brief X.509 status: unknown critical extension in certificate. */ +#define BR_ERR_X509_CRITICAL_EXTENSION 57 + +/** \brief X.509 status: not a CA, or path length constraint violation */ +#define BR_ERR_X509_NOT_CA 58 + +/** \brief X.509 status: Key Usage extension prohibits intended usage. */ +#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59 + +/** \brief X.509 status: public key found in certificate is too small. */ +#define BR_ERR_X509_WEAK_PUBLIC_KEY 60 + +/** \brief X.509 status: chain could not be linked to a trust anchor. */ +#define BR_ERR_X509_NOT_TRUSTED 62 + +/** + * \brief Aggregate structure for public keys. + */ +typedef struct { + /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */ + unsigned char key_type; + /** \brief Actual public key. */ + union { + /** \brief RSA public key. */ + br_rsa_public_key rsa; + /** \brief EC public key. */ + br_ec_public_key ec; + } key; +} br_x509_pkey; + +/** + * \brief Distinguished Name (X.500) structure. + * + * The DN is DER-encoded. + */ +typedef struct { + /** \brief Encoded DN data. */ + unsigned char *data; + /** \brief Encoded DN length (in bytes). */ + size_t len; +} br_x500_name; + +/** + * \brief Trust anchor structure. + */ +typedef struct { + /** \brief Encoded DN (X.500 name). */ + br_x500_name dn; + /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */ + unsigned flags; + /** \brief Anchor public key. */ + br_x509_pkey pkey; +} br_x509_trust_anchor; + +/** + * \brief Trust anchor flag: CA. + * + * A "CA" anchor is deemed fit to verify signatures on certificates. + * A "non-CA" anchor is accepted only for direct trust (server's + * certificate name and key match the anchor). + */ +#define BR_X509_TA_CA 0x0001 + +/* + * Key type: combination of a basic key type (low 4 bits) and some + * optional flags. + * + * For a public key, the basic key type only is set. + * + * For an expected key type, the flags indicate the intended purpose(s) + * for the key; the basic key type may be set to 0 to indicate that any + * key type compatible with the indicated purpose is acceptable. + */ +/** \brief Key type: algorithm is RSA. */ +#define BR_KEYTYPE_RSA 1 +/** \brief Key type: algorithm is EC. */ +#define BR_KEYTYPE_EC 2 + +/** + * \brief Key type: usage is "key exchange". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher + * suites). + */ +#define BR_KEYTYPE_KEYX 0x10 + +/** + * \brief Key type: usage is "signature". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites). + */ +#define BR_KEYTYPE_SIGN 0x20 + +/* + * start_chain Called when a new chain is started. If 'server_name' + * is not NULL and non-empty, then it is a name that + * should be looked for in the EE certificate (in the + * SAN extension as dNSName, or in the subjectDN's CN + * if there is no SAN extension). + * The caller ensures that the provided 'server_name' + * pointer remains valid throughout validation. + * + * start_cert Begins a new certificate in the chain. The provided + * length is in bytes; this is the total certificate length. + * + * append Get some additional bytes for the current certificate. + * + * end_cert Ends the current certificate. + * + * end_chain Called at the end of the chain. Returned value is + * 0 on success, or a non-zero error code. + * + * get_pkey Returns the EE certificate public key. + * + * For a complete chain, start_chain() and end_chain() are always + * called. For each certificate, start_cert(), some append() calls, then + * end_cert() are called, in that order. There may be no append() call + * at all if the certificate is empty (which is not valid but may happen + * if the peer sends exactly that). + * + * get_pkey() shall return a pointer to a structure that is valid as + * long as a new chain is not started. This may be a sub-structure + * within the context for the engine. This function MAY return a valid + * pointer to a public key even in some cases of validation failure, + * depending on the validation engine. + */ + +/** + * \brief Class type for an X.509 engine. + * + * A certificate chain validation uses a caller-allocated context, which + * contains the running state for that validation. Methods are called + * in due order: + * + * - `start_chain()` is called at the start of the validation. + * - Certificates are processed one by one, in SSL order (end-entity + * comes first). For each certificate, the following methods are + * called: + * + * - `start_cert()` at the beginning of the certificate. + * - `append()` is called zero, one or more times, to provide + * the certificate (possibly in chunks). + * - `end_cert()` at the end of the certificate. + * + * - `end_chain()` is called when the last certificate in the chain + * was processed. + * - `get_pkey()` is called after chain processing, if the chain + * validation was successful. + * + * A context structure may be reused; the `start_chain()` method shall + * ensure (re)initialisation. + */ +typedef struct br_x509_class_ br_x509_class; +struct br_x509_class_ { + /** + * \brief X.509 context size, in bytes. + */ + size_t context_size; + + /** + * \brief Start a new chain. + * + * This method shall set the vtable (first field) of the context + * structure. + * + * The `server_name`, if not `NULL`, will be considered as a + * fully qualified domain name, to be matched against the `dNSName` + * elements of the end-entity certificate's SAN extension (if there + * is no SAN, then the Common Name from the subjectDN will be used). + * If `server_name` is `NULL` then no such matching is performed. + * + * \param ctx validation context. + * \param server_name server name to match (or `NULL`). + */ + void (*start_chain)(const br_x509_class **ctx, + const char *server_name); + + /** + * \brief Start a new certificate. + * + * \param ctx validation context. + * \param length new certificate length (in bytes). + */ + void (*start_cert)(const br_x509_class **ctx, uint32_t length); + + /** + * \brief Receive some bytes for the current certificate. + * + * This function may be called several times in succession for + * a given certificate. The caller guarantees that for each + * call, `len` is not zero, and the sum of all chunk lengths + * for a certificate matches the total certificate length which + * was provided in the previous `start_cert()` call. + * + * If the new certificate is empty (no byte at all) then this + * function won't be called at all. + * + * \param ctx validation context. + * \param buf certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ + void (*append)(const br_x509_class **ctx, + const unsigned char *buf, size_t len); + + /** + * \brief Finish the current certificate. + * + * This function is called when the end of the current certificate + * is reached. + * + * \param ctx validation context. + */ + void (*end_cert)(const br_x509_class **ctx); + + /** + * \brief Finish the chain. + * + * This function is called at the end of the chain. It shall + * return either 0 if the validation was successful, or a + * non-zero error code. The `BR_ERR_X509_*` constants are + * error codes, though other values may be possible. + * + * \param ctx validation context. + * \return 0 on success, or a non-zero error code. + */ + unsigned (*end_chain)(const br_x509_class **ctx); + + /** + * \brief Get the resulting end-entity public key. + * + * The decoded public key is returned. The returned pointer + * may be valid only as long as the context structure is + * unmodified, i.e. it may cease to be valid if the context + * is released or reused. + * + * This function _may_ return `NULL` if the validation failed. + * However, returning a public key does not mean that the + * validation was wholly successful; some engines may return + * a decoded public key even if the chain did not end on a + * trusted anchor. + * + * If validation succeeded and `usage` is not `NULL`, then + * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN` + * and/or `BR_KEYTYPE_KEYX` that specifies the validated key + * usage types. It is the caller's responsibility to check + * that value against the intended use of the public key. + * + * \param ctx validation context. + * \return the end-entity public key, or `NULL`. + */ + const br_x509_pkey *(*get_pkey)( + const br_x509_class *const *ctx, unsigned *usages); +}; + +/** + * \brief The "known key" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "known key" engine returns an externally configured public key, + * and totally ignores the certificate contents. + */ +typedef struct { + /** \brief Reference to the context vtable. */ + const br_x509_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_x509_pkey pkey; + unsigned usages; +#endif +} br_x509_knownkey_context; + +/** + * \brief Class instance for the "known key" X.509 engine. + */ +extern const br_x509_class br_x509_knownkey_vtable; + +/** + * \brief Initialize a "known key" X.509 engine with a known RSA public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, + const br_rsa_public_key *pk, unsigned usages); + +/** + * \brief Initialize a "known key" X.509 engine with a known EC public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, + const br_ec_public_key *pk, unsigned usages); + +#ifndef BR_DOXYGEN_IGNORE +/* + * The minimal X.509 engine has some state buffers which must be large + * enough to simultaneously accommodate: + * -- the public key extracted from the current certificate; + * -- the signature on the current certificate or on the previous + * certificate; + * -- the public key extracted from the EE certificate. + * + * We store public key elements in their raw unsigned big-endian + * encoding. We want to support up to RSA-4096 with a short (up to 64 + * bits) public exponent, thus a buffer for a public key must have + * length at least 520 bytes. Similarly, a RSA-4096 signature has length + * 512 bytes. + * + * Though RSA public exponents can formally be as large as the modulus + * (mathematically, even larger exponents would work, but PKCS#1 forbids + * them), exponents that do not fit on 32 bits are extremely rare, + * notably because some widespread implementations (e.g. Microsoft's + * CryptoAPI) don't support them. Moreover, large public exponent do not + * seem to imply any tangible security benefit, and they increase the + * cost of public key operations. The X.509 "minimal" engine will tolerate + * public exponents of arbitrary size as long as the modulus and the + * exponent can fit together in the dedicated buffer. + * + * EC public keys are shorter than RSA public keys; even with curve + * NIST P-521 (the largest curve we care to support), a public key is + * encoded over 133 bytes only. + */ +#define BR_X509_BUFSIZE_KEY 520 +#define BR_X509_BUFSIZE_SIG 512 +#endif + +/** + * \brief Type for receiving a name element. + * + * An array of such structures can be provided to the X.509 decoding + * engines. If the specified elements are found in the certificate + * subject DN or the SAN extension, then the name contents are copied + * as zero-terminated strings into the buffer. + * + * The decoder converts TeletexString and BMPString to UTF8String, and + * ensures that the resulting string is zero-terminated. If the string + * does not fit in the provided buffer, then the copy is aborted and an + * error is reported. + */ +typedef struct { + /** + * \brief Element OID. + * + * For X.500 name elements (to be extracted from the subject DN), + * this is the encoded OID for the requested name element; the + * first byte shall contain the length of the DER-encoded OID + * value, followed by the OID value (for instance, OID 2.5.4.3, + * for id-at-commonName, will be `03 55 04 03`). This is + * equivalent to full DER encoding with the length but without + * the tag. + * + * For SAN name elements, the first byte (`oid[0]`) has value 0, + * followed by another byte that matches the expected GeneralName + * tag. Allowed second byte values are then: + * + * - 1: `rfc822Name` + * + * - 2: `dNSName` + * + * - 6: `uniformResourceIdentifier` + * + * - 0: `otherName` + * + * If first and second byte are 0, then this is a SAN element of + * type `otherName`; the `oid[]` array should then contain, right + * after the two bytes of value 0, an encoded OID (with the same + * conventions as for X.500 name elements). If a match is found + * for that OID, then the corresponding name element will be + * extracted, as long as it is a supported string type. + */ + const unsigned char *oid; + + /** + * \brief Destination buffer. + */ + char *buf; + + /** + * \brief Length (in bytes) of the destination buffer. + * + * The buffer MUST NOT be smaller than 1 byte. + */ + size_t len; + + /** + * \brief Decoding status. + * + * Status is 0 if the name element was not found, 1 if it was + * found and decoded, or -1 on error. Error conditions include + * an unrecognised encoding, an invalid encoding, or a string + * too large for the destination buffer. + */ + int status; + +} br_name_element; + +/** + * \brief Callback for validity date checks. + * + * The function receives as parameter an arbitrary user-provided context, + * and the notBefore and notAfter dates specified in an X.509 certificate, + * both expressed as a number of days and a number of seconds: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * Each date and time is understood in the UTC time zone. The "Unix + * Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and + * seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * This function must return -1 if the current date is strictly before + * the "notBefore" time, or +1 if the current date is strictly after the + * "notAfter" time. If neither condition holds, then the function returns + * 0, which means that the current date falls within the validity range of + * the certificate. If the function returns a value distinct from -1, 0 + * and +1, then this is interpreted as an unavailability of the current + * time, which normally ends the validation process with a + * `BR_ERR_X509_TIME_UNKNOWN` error. + * + * During path validation, this callback will be invoked for each + * considered X.509 certificate. Validation fails if any of the calls + * returns a non-zero value. + * + * The context value is an abritrary pointer set by the caller when + * configuring this callback. + * + * \param tctx context pointer. + * \param not_before_days notBefore date (days since Jan 1st, 0 AD). + * \param not_before_seconds notBefore time (seconds, at most 86400). + * \param not_after_days notAfter date (days since Jan 1st, 0 AD). + * \param not_after_seconds notAfter time (seconds, at most 86400). + * \return -1, 0 or +1. + */ +typedef int (*br_x509_time_check)(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds); + +/** + * \brief The "minimal" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "minimal" engine performs a rudimentary but serviceable X.509 path + * validation. + */ +typedef struct { + const br_x509_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the EE public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[31]; + uint32_t rp_stack[31]; + int err; + + /* Server name to match with the SAN / CN of the EE certificate. */ + const char *server_name; + + /* Validated key usages. */ + unsigned char key_usages; + + /* Explicitly set date and time. */ + uint32_t days, seconds; + + /* Current certificate length (in bytes). Set to 0 when the + certificate has been fully processed. */ + uint32_t cert_length; + + /* Number of certificates processed so far in the current chain. + It is incremented at the end of the processing of a certificate, + so it is 0 for the EE. */ + uint32_t num_certs; + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Buffer for EE public key data. */ + unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Buffer for currently decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Signature type: signer key type, offset to the hash + function OID (in the T0 data block) and hash function + output length (TBS hash length). */ + unsigned char cert_signer_key_type; + uint16_t cert_sig_hash_oid; + unsigned char cert_sig_hash_len; + + /* Current/last certificate signature. */ + unsigned char cert_sig[BR_X509_BUFSIZE_SIG]; + uint16_t cert_sig_len; + + /* Minimum RSA key length (difference in bytes from 128). */ + int16_t min_rsa_size; + + /* Configured trust anchors. */ + const br_x509_trust_anchor *trust_anchors; + size_t trust_anchors_num; + + /* + * Multi-hasher for the TBS. + */ + unsigned char do_mhash; + br_multihash_context mhash; + unsigned char tbs_hash[64]; + + /* + * Simple hasher for the subject/issuer DN. + */ + unsigned char do_dn_hash; + const br_hash_class *dn_hash_impl; + br_hash_compat_context dn_hash; + unsigned char current_dn_hash[64]; + unsigned char next_dn_hash[64]; + unsigned char saved_dn_hash[64]; + + /* + * Name elements to gather. + */ + br_name_element *name_elts; + size_t num_name_elts; + + /* + * Callback function (and context) to get the current date. + */ + void *itime_ctx; + br_x509_time_check itime; + + /* + * Public key cryptography implementations (signature verification). + */ + br_rsa_pkcs1_vrfy irsa; + br_ecdsa_vrfy iecdsa; + const br_ec_impl *iec; +#endif + +} br_x509_minimal_context; + +/** + * \brief Class instance for the "minimal" X.509 engine. + */ +extern const br_x509_class br_x509_minimal_vtable; + +/** + * \brief Initialise a "minimal" X.509 engine. + * + * The `dn_hash_impl` parameter shall be a hash function internally used + * to match X.500 names (subject/issuer DN, and anchor names). Any standard + * hash function may be used, but a collision-resistant hash function is + * advised. + * + * After initialization, some implementations for signature verification + * (hash functions and signature algorithms) MUST be added. + * + * \param ctx context to initialise. + * \param dn_hash_impl hash function for DN comparisons. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set a supported hash function in an X.509 "minimal" engine. + * + * Hash functions are used with signature verification algorithms. + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the hash functions it shall support for that + * purpose. The hash function identifier MUST be one of the standard + * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 and SHA-512). + * + * If `impl` is `NULL`, this _removes_ support for the designated + * hash function. + * + * \param ctx validation context. + * \param id hash function identifier (from 1 to 6). + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_x509_minimal_set_hash(br_x509_minimal_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Set a RSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. If `irsa` is `0`, then the RSA support + * is disabled. + * + * \param ctx validation context. + * \param irsa RSA signature verification implementation (or `0`). + */ +static inline void +br_x509_minimal_set_rsa(br_x509_minimal_context *ctx, + br_rsa_pkcs1_vrfy irsa) +{ + ctx->irsa = irsa; +} + +/** + * \brief Set a ECDSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. + * + * If `iecdsa` is `0`, then this call disables ECDSA support; in that + * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function + * that verifies ECDSA signatures with format "asn1", and it will use + * `iec` as underlying elliptic curve support. + * + * \param ctx validation context. + * \param iec elliptic curve implementation (or `NULL`). + * \param iecdsa ECDSA implementation (or `0`). + */ +static inline void +br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, + const br_ec_impl *iec, br_ecdsa_vrfy iecdsa) +{ + ctx->iecdsa = iecdsa; + ctx->iec = iec; +} + +/** + * \brief Initialise a "minimal" X.509 engine with default algorithms. + * + * This function performs the same job as `br_x509_minimal_init()`, but + * also sets implementations for RSA, ECDSA, and the standard hash + * functions. + * + * \param ctx context to initialise. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init_full(br_x509_minimal_context *ctx, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set the validation time for the X.509 "minimal" engine. + * + * The validation time is set as two 32-bit integers, for days and + * seconds since a fixed epoch: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * The validation date and time is understood in the UTC time zone. The + * "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 + * and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * If the validation date and time are not explicitly set, but BearSSL + * was compiled with support for the system clock on the underlying + * platform, then the current time will automatically be used. Otherwise, + * not setting the validation date and time implies a validation + * failure (except in case of direct trust of the EE key). + * + * \param ctx validation context. + * \param days days since January 1st, 0 AD (Gregorian calendar). + * \param seconds seconds since midnight (0 to 86400). + */ +static inline void +br_x509_minimal_set_time(br_x509_minimal_context *ctx, + uint32_t days, uint32_t seconds) +{ + ctx->days = days; + ctx->seconds = seconds; + ctx->itime = 0; +} + +/** + * \brief Set the validity range callback function for the X.509 + * "minimal" engine. + * + * The provided function will be invoked to check whether the validation + * date is within the validity range for a given X.509 certificate; a + * call will be issued for each considered certificate. The provided + * context pointer (itime_ctx) will be passed as first parameter to the + * callback. + * + * \param tctx context for callback invocation. + * \param cb callback function. + */ +static inline void +br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx, + void *itime_ctx, br_x509_time_check itime) +{ + ctx->itime_ctx = itime_ctx; + ctx->itime = itime; +} + +/** + * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal" + * engine). + * + * The RSA key length is expressed in bytes. The default minimum key + * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter + * than the configured length will be rejected, implying validation + * failure. This setting applies to keys extracted from certificates + * (both end-entity, and intermediate CA) but not to "CA" trust anchors. + * + * \param ctx validation context. + * \param byte_length minimum RSA key length, **in bytes** (not bits). + */ +static inline void +br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) +{ + ctx->min_rsa_size = (int16_t)(byte_length - 128); +} + +/** + * \brief Set the name elements to gather. + * + * The provided array is linked in the context. The elements are + * gathered from the EE certificate. If the same element type is + * requested several times, then the relevant structures will be filled + * in the order the matching values are encountered in the certificate. + * + * \param ctx validation context. + * \param elts array of name element structures to fill. + * \param num_elts number of name element structures to fill. + */ +static inline void +br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, + br_name_element *elts, size_t num_elts) +{ + ctx->name_elts = elts; + ctx->num_name_elts = num_elts; +} + +/** + * \brief X.509 decoder context. + * + * This structure is _not_ for X.509 validation, but for extracting + * names and public keys from encoded certificates. Intended usage is + * to use (self-signed) certificates as trust anchors. + * + * Contents are opaque and shall not be accessed directly. + */ +typedef struct { + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Flag set when decoding succeeds. */ + unsigned char decoded; + + /* Validity dates. */ + uint32_t notbefore_days, notbefore_seconds; + uint32_t notafter_days, notafter_seconds; + + /* The "CA" flag. This is set to true if the certificate contains + a Basic Constraints extension that asserts CA status. */ + unsigned char isCA; + + /* DN processing: the subject DN is extracted and pushed to the + provided callback. */ + unsigned char copy_dn; + void *append_dn_ctx; + void (*append_dn)(void *ctx, const void *buf, size_t len); + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* Buffer for decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Type of key and hash function used in the certificate signature. */ + unsigned char signer_key_type; + unsigned char signer_hash_id; +#endif + +} br_x509_decoder_context; + +/** + * \brief Initialise an X.509 decoder context for processing a new + * certificate. + * + * The `append_dn()` callback (with opaque context `append_dn_ctx`) + * will be invoked to receive, chunk by chunk, the certificate's + * subject DN. If `append_dn` is `0` then the subject DN will be + * ignored. + * + * \param ctx X.509 decoder context to initialise. + * \param append_dn DN receiver callback (or `0`). + * \param append_dn_ctx context for the DN receiver callback. + */ +void br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx); + +/** + * \brief Push some certificate bytes into a decoder context. + * + * If `len` is non-zero, then that many bytes are pushed, from address + * `data`, into the provided decoder context. + * + * \param ctx X.509 decoder context. + * \param data certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ +void br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Obtain the decoded public key. + * + * Returned value is a pointer to a structure internal to the decoder + * context; releasing or reusing the decoder context invalidates that + * structure. + * + * If decoding was not finished, or failed, then `NULL` is returned. + * + * \param ctx X.509 decoder context. + * \return the public key, or `NULL` on unfinished/error. + */ +static inline br_x509_pkey * +br_x509_decoder_get_pkey(br_x509_decoder_context *ctx) +{ + if (ctx->decoded && ctx->err == 0) { + return &ctx->pkey; + } else { + return NULL; + } +} + +/** + * \brief Get decoder error status. + * + * If no error was reported yet but the certificate decoding is not + * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding + * was successful, then 0 is returned. + * + * \param ctx X.509 decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_x509_decoder_last_error(br_x509_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (!ctx->decoded) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the "isCA" flag from an X.509 decoder context. + * + * This flag is set if the decoded certificate claims to be a CA through + * a Basic Constraints extension. This flag should not be read before + * decoding completed successfully. + * + * \param ctx X.509 decoder context. + * \return the "isCA" flag. + */ +static inline int +br_x509_decoder_isCA(br_x509_decoder_context *ctx) +{ + return ctx->isCA; +} + +/** + * \brief Get the issuing CA key type (type of algorithm used to sign the + * decoded certificate). + * + * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned + * if the signature type was not recognised. + * + * \param ctx X.509 decoder context. + * \return the issuing CA key type. + */ +static inline int +br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx) +{ + return ctx->signer_key_type; +} + +/** + * \brief Get the identifier for the hash function used to sign the decoded + * certificate. + * + * This is 0 if the hash function was not recognised. + * + * \param ctx X.509 decoder context. + * \return the signature hash function identifier. + */ +static inline int +br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx) +{ + return ctx->signer_hash_id; +} + +/** + * \brief Type for an X.509 certificate (DER-encoded). + */ +typedef struct { + /** \brief The DER-encoded certificate data. */ + unsigned char *data; + /** \brief The DER-encoded certificate length (in bytes). */ + size_t data_len; +} br_x509_certificate; + +/** + * \brief Private key decoder context. + * + * The private key decoder recognises RSA and EC private keys, either in + * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 + * archive (again DER-encoded). + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the private key. */ + union { + br_rsa_private_key rsa; + br_ec_private_key ec; + } key; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Private key data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Decoded key type; 0 until decoding is complete. */ + unsigned char key_type; + + /* Buffer for the private key elements. It shall be large enough + to accommodate all elements for a RSA-4096 private key (roughly + five 2048-bit integers, possibly a bit more). */ + unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; +#endif +} br_skey_decoder_context; + +/** + * \brief Initialise a private key decoder context. + * + * \param ctx key decoder context to initialise. + */ +void br_skey_decoder_init(br_skey_decoder_context *ctx); + +/** + * \brief Push some data bytes into a private key decoder context. + * + * If `len` is non-zero, then that many data bytes, starting at address + * `data`, are pushed into the decoder. + * + * \param ctx key decoder context. + * \param data private key data chunk. + * \param len private key data chunk length (in bytes). + */ +void br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Get the decoding status for a private key. + * + * Decoding status is 0 on success, or a non-zero error code. If the + * decoding is unfinished when this function is called, then the + * status code `BR_ERR_X509_TRUNCATED` is returned. + * + * \param ctx key decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_skey_decoder_last_error(const br_skey_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (ctx->key_type == 0) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the decoded private key type. + * + * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is + * not finished or failed, then 0 is returned. + * + * \param ctx key decoder context. + * \return decoded private key type, or 0. + */ +static inline int +br_skey_decoder_key_type(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0) { + return ctx->key_type; + } else { + return 0; + } +} + +/** + * \brief Get the decoded RSA private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not RSA. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded RSA private key, or `NULL`. + */ +static inline const br_rsa_private_key * +br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { + return &ctx->key.rsa; + } else { + return NULL; + } +} + +/** + * \brief Get the decoded EC private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not EC. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded EC private key, or `NULL`. + */ +static inline const br_ec_private_key * +br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { + return &ctx->key.ec; + } else { + return NULL; + } +} + +/** + * \brief Encode an RSA private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER + * encoding rules. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an RSA private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" + * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an EC private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is `NULL`, then the encoded key will not include the public key + * in its `publicKey` field (which is nominally optional). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief Encode an EC private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). The curve is identified + * by an OID provided as parameters to the `privateKeyAlgorithm` + * field. The private key value (contents of the `privateKey` field) + * contains the DER encoding of the `ECPrivateKey` type defined in + * RFC 5915, without the `parameters` field (since they would be + * redundant with the information in `privateKeyAlgorithm`). + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is not `NULL`, then the encoded public key is included in the + * `publicKey` field of the private key value (but not in the `publicKey` + * field of the PKCS#8 `OneAsymmetricKey` wrapper). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief PEM banner for RSA private key (raw). + */ +#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" + +/** + * \brief PEM banner for EC private key (raw). + */ +#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" + +/** + * \brief PEM banner for an RSA or EC private key in PKCS#8 format. + */ +#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_aead.h b/template/sysroot/include/bearssl_aead.h new file mode 100644 index 0000000..8e35a1f --- /dev/null +++ b/template/sysroot/include/bearssl_aead.h @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_AEAD_H__ +#define BR_BEARSSL_AEAD_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_aead.h + * + * # Authenticated Encryption with Additional Data + * + * This file documents the API for AEAD encryption. + * + * + * ## Procedural API + * + * An AEAD algorithm processes messages and provides confidentiality + * (encryption) and checked integrity (MAC). It uses the following + * parameters: + * + * - A symmetric key. Exact size depends on the AEAD algorithm. + * + * - A nonce (IV). Size depends on the AEAD algorithm; for most + * algorithms, it is crucial for security that any given nonce + * value is never used twice for the same key and distinct + * messages. + * + * - Data to encrypt and protect. + * + * - Additional authenticated data, which is covered by the MAC but + * otherwise left untouched (i.e. not encrypted). + * + * The AEAD algorithm encrypts the data, and produces an authentication + * tag. It is assumed that the encrypted data, the tag, the additional + * authenticated data and the nonce are sent to the receiver; the + * additional data and the nonce may be implicit (e.g. using elements of + * the underlying transport protocol, such as record sequence numbers). + * The receiver will recompute the tag value and compare it with the one + * received; if they match, then the data is correct, and can be + * decrypted and used; otherwise, at least one of the elements was + * altered in transit, normally leading to wholesale rejection of the + * complete message. + * + * For each AEAD algorithm, identified by a symbolic name (hereafter + * denoted as "`xxx`"), the following functions are defined: + * + * - `br_xxx_init()` + * + * Initialise the AEAD algorithm, on a provided context structure. + * Exact parameters depend on the algorithm, and may include + * pointers to extra implementations and context structures. The + * secret key is provided at this point, either directly or + * indirectly. + * + * - `br_xxx_reset()` + * + * Start a new AEAD computation. The nonce value is provided as + * parameter to this function. + * + * - `br_xxx_aad_inject()` + * + * Inject some additional authenticated data. Additional data may + * be provided in several chunks of arbitrary length. + * + * - `br_xxx_flip()` + * + * This function MUST be called after injecting all additional + * authenticated data, and before beginning to encrypt the plaintext + * (or decrypt the ciphertext). + * + * - `br_xxx_run()` + * + * Process some plaintext (to encrypt) or ciphertext (to decrypt). + * Encryption/decryption is done in place. Data may be provided in + * several chunks of arbitrary length. + * + * - `br_xxx_get_tag()` + * + * Compute the authentication tag. All message data (encrypted or + * decrypted) must have been injected at that point. Also, this + * call may modify internal context elements, so it may be called + * only once for a given AEAD computation. + * + * - `br_xxx_check_tag()` + * + * An alternative to `br_xxx_get_tag()`, meant to be used by the + * receiver: the authentication tag is internally recomputed, and + * compared with the one provided as parameter. + * + * This API makes the following assumptions on the AEAD algorithm: + * + * - Encryption does not expand the size of the ciphertext; there is + * no padding. This is true of most modern AEAD modes such as GCM. + * + * - The additional authenticated data must be processed first, + * before the encrypted/decrypted data. + * + * - Nonce, plaintext and additional authenticated data all consist + * in an integral number of bytes. There is no provision to use + * elements whose length in bits is not a multiple of 8. + * + * Each AEAD algorithm has its own requirements and limits on the sizes + * of additional data and plaintext. This API does not provide any + * way to report invalid usage; it is up to the caller to ensure that + * the provided key, nonce, and data elements all fit the algorithm's + * requirements. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `reset` + * + * Pointer to the reset function, that allows starting a new + * computation. + * + * - `aad_inject` + * + * Pointer to the additional authenticated data injection function. + * + * - `flip` + * + * Pointer to the function that transitions from additional data + * to main message data processing. + * + * - `get_tag` + * + * Pointer to the function that computes and returns the tag. + * + * - `check_tag` + * + * Pointer to the function that computes and verifies the tag against + * a received value. + * + * Note that there is no OOP method for context initialisation: the + * various AEAD algorithms have different requirements that would not + * map well to a single initialisation API. + * + * The OOP API is not provided for CCM, due to its specific requirements + * (length of plaintext must be known in advance). + */ + +/** + * \brief Class type of an AEAD algorithm. + */ +typedef struct br_aead_class_ br_aead_class; +struct br_aead_class_ { + + /** + * \brief Size (in bytes) of authentication tags created by + * this AEAD algorithm. + */ + size_t tag_size; + + /** + * \brief Reset an AEAD context. + * + * This function resets an already initialised AEAD context for + * a new computation run. Implementations and keys are + * conserved. This function can be called at any time; it + * cancels any ongoing AEAD computation that uses the provided + * context structure. + + * The provided IV is a _nonce_. Each AEAD algorithm has its + * own requirements on IV size and contents; for most of them, + * it is crucial to security that each nonce value is used + * only once for a given secret key. + * + * \param cc AEAD context structure. + * \param iv AEAD nonce to use. + * \param len AEAD nonce length (in bytes). + */ + void (*reset)(const br_aead_class **cc, const void *iv, size_t len); + + /** + * \brief Inject additional authenticated data. + * + * The provided data is injected into a running AEAD + * computation. Additional data must be injected _before_ the + * call to `flip()`. Additional data can be injected in several + * chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ + void (*aad_inject)(const br_aead_class **cc, + const void *data, size_t len); + + /** + * \brief Finish injection of additional authenticated data. + * + * This function MUST be called before beginning the actual + * encryption or decryption (with `run()`), even if no + * additional authenticated data was injected. No additional + * authenticated data may be injected after this function call. + * + * \param cc AEAD context structure. + */ + void (*flip)(const br_aead_class **cc); + + /** + * \brief Encrypt or decrypt some data. + * + * Data encryption or decryption can be done after `flip()` has + * been called on the context. If `encrypt` is non-zero, then + * the provided data shall be plaintext, and it is encrypted in + * place. Otherwise, the data shall be ciphertext, and it is + * decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ + void (*run)(const br_aead_class **cc, int encrypt, + void *data, size_t len); + + /** + * \brief Compute authentication tag. + * + * Compute the AEAD authentication tag. The tag length depends + * on the AEAD algorithm; it is written in the provided `tag` + * buffer. This call terminates the AEAD run: no data may be + * processed with that AEAD context afterwards, until `reset()` + * is called to initiate a new AEAD run. + * + * The tag value must normally be sent along with the encrypted + * data. When decrypting, the tag value must be recomputed and + * compared with the received tag: if the two tag values differ, + * then either the tag or the encrypted data was altered in + * transit. As an alternative to this function, the + * `check_tag()` function may be used to compute and check the + * tag value. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + */ + void (*get_tag)(const br_aead_class **cc, void *tag); + + /** + * \brief Compute and check authentication tag. + * + * This function is an alternative to `get_tag()`, and is + * normally used on the receiving end (i.e. when decrypting + * messages). The tag value is recomputed and compared with the + * provided tag value. If they match, 1 is returned; on + * mismatch, 0 is returned. A returned value of 0 means that the + * data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag)(const br_aead_class **cc, const void *tag); + + /** + * \brief Compute authentication tag (with truncation). + * + * This function is similar to `get_tag()`, except that the tag + * length is provided. Some AEAD algorithms allow several tag + * lengths, usually by truncating the normal tag. Shorter tags + * mechanically increase success probability of forgeries. + * The range of allowed tag lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + * \param len tag length (in bytes). + */ + void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len); + + /** + * \brief Compute and check authentication tag (with truncation). + * + * This function is similar to `check_tag()` except that it + * works over an explicit tag length. See `get_tag()` for a + * discussion of explicit tag lengths; the range of allowed tag + * lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag_trunc)(const br_aead_class **cc, + const void *tag, size_t len); +}; + +/** + * \brief Context structure for GCM. + * + * GCM is an AEAD mode that combines a block cipher in CTR mode with a + * MAC based on GHASH, to provide authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with GCM. + * + * - The nonce can have any length, from 0 up to 2^64-1 bits; however, + * 96-bit nonces (12 bytes) are recommended (nonces with a length + * distinct from 12 bytes are internally hashed, which risks reusing + * nonce value with a small but not always negligible probability). + * + * - Additional authenticated data may have length up to 2^64-1 bits. + * + * - Message length may range up to 2^39-256 bits at most. + * + * - The authentication tag has length 16 bytes. + * + * The GCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * GCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctr_class **bctx; + br_ghash gh; + unsigned char h[16]; + unsigned char j0_1[12]; + unsigned char buf[16]; + unsigned char y[16]; + uint32_t j0_2, jc; + uint64_t count_aad, count_ctr; +#endif +} br_gcm_context; + +/** + * \brief Initialize a GCM context. + * + * A block cipher implementation, with its initialised context structure, + * is provided. The block cipher MUST use 16-byte blocks in CTR mode, + * and its secret key MUST have been already set in the provided context. + * A GHASH implementation must also be provided. The parameters are linked + * in the GCM context. + * + * After this function has been called, the `br_gcm_reset()` function must + * be called, to provide the IV for GCM computation. + * + * \param ctx GCM context structure. + * \param bctx block cipher context (already initialised with secret key). + * \param gh GHASH implementation. + */ +void br_gcm_init(br_gcm_context *ctx, + const br_block_ctr_class **bctx, br_ghash gh); + +/** + * \brief Reset a GCM context. + * + * This function resets an already initialised GCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing GCM computation that + * uses the provided context structure. + * + * The provided IV is a _nonce_. It is critical to GCM security that IV + * values are not repeated for the same encryption key. IV can have + * arbitrary length (up to 2^64-1 bits), but the "normal" length is + * 96 bits (12 bytes). + * + * \param ctx GCM context structure. + * \param iv GCM nonce to use. + * \param len GCM nonce length (in bytes). + */ +void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len); + +/** + * \brief Inject additional authenticated data into GCM. + * + * The provided data is injected into a running GCM computation. Additional + * data must be injected _before_ the call to `br_gcm_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the maximum total size of additional authenticated data is 2^64-1 + * bits. + * + * \param ctx GCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into GCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_gcm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx GCM context structure. + */ +void br_gcm_flip(br_gcm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with GCM. + * + * Data encryption or decryption can be done after `br_gcm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. The maximum + * total length for data is 2^39-256 bits, i.e. about 65 gigabytes. + * + * \param ctx GCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute GCM authentication tag. + * + * Compute the GCM authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * GCM run: no data may be processed with that GCM context afterwards, + * until `br_gcm_reset()` is called to initiate a new GCM run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_gcm_get_tag(br_gcm_context *ctx, void *tag); + +/** + * \brief Compute and check GCM authentication tag. + * + * This function is an alternative to `br_gcm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag); + +/** + * \brief Compute GCM authentication tag (with truncation). + * + * This function is similar to `br_gcm_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the GCM run: no data may be processed with that GCM context + * afterwards, until `br_gcm_reset()` is called to initiate a new GCM + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check GCM authentication tag (with truncation). + * + * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for GCM. + */ +extern const br_aead_class br_gcm_vtable; + +/** + * \brief Context structure for EAX. + * + * EAX is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with EAX + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The nonce can have any length, as long as nonce values are + * not reused (thus, if nonces are randomly selected, the nonce + * size should be such that reuse probability is negligible). + * + * - Additional authenticated data length is unlimited. + * + * - Message length is unlimited. + * + * - The authentication tag has length 16 bytes. + * + * The EAX initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * EAX context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char L2[16]; + unsigned char L4[16]; + unsigned char nonce[16]; + unsigned char head[16]; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char buf[16]; + size_t ptr; +#endif +} br_eax_context; + +/** + * \brief EAX captured state. + * + * Some internal values computed by EAX may be captured at various + * points, and reused for another EAX run with the same secret key, + * for lower per-message overhead. Captured values do not depend on + * the nonce. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char st[3][16]; +#endif +} br_eax_state; + +/** + * \brief Initialize an EAX context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the EAX context. + * + * After this function has been called, the `br_eax_reset()` function must + * be called, to provide the nonce for EAX computation. + * + * \param ctx EAX context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Capture pre-AAD state. + * + * This function precomputes key-dependent data, and stores it in the + * provided `st` structure. This structure should then be used with + * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()` + * and then used with `br_eax_reset_post_aad()`. + * + * The EAX context structure is unmodified by this call. + * + * \param ctx EAX context structure. + * \param st recipient for captured state. + */ +void br_eax_capture(const br_eax_context *ctx, br_eax_state *st); + +/** + * \brief Reset an EAX context. + * + * This function resets an already initialised EAX context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing EAX computation that + * uses the provided context structure. + * + * It is critical to EAX security that nonce values are not repeated for + * the same encryption key. Nonces can have arbitrary length. If nonces + * are randomly generated, then a nonce length of at least 128 bits (16 + * bytes) is recommended, to make nonce reuse probability sufficiently + * low. + * + * \param ctx EAX context structure. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a pre-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * but not updated with `br_eax_get_aad_mac()`. + * + * After this function is called, additional authenticated data MUST + * be injected. At least one byte of additional authenticated data + * MUST be provided with `br_eax_aad_inject()`; computation result will + * be incorrect if `br_eax_flip()` is called right away. + * + * After injection of the AAD and call to `br_eax_flip()`, at least + * one message byte must be provided. Empty messages are not supported + * with this reset mode. + * + * \param ctx EAX context structure. + * \param st pre-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a post-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * and then updated with `br_eax_get_aad_mac()`. + * + * After this function is called, message data MUST be injected. The + * `br_eax_flip()` function MUST NOT be called. At least one byte of + * message data MUST be provided with `br_eax_run()`; empty messages + * are not supported with this reset mode. + * + * \param ctx EAX context structure. + * \param st post-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Inject additional authenticated data into EAX. + * + * The provided data is injected into a running EAX computation. Additional + * data must be injected _before_ the call to `br_eax_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the total amount of additional authenticated data is unlimited. + * + * \param ctx EAX context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into EAX. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_eax_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx EAX context structure. + */ +void br_eax_flip(br_eax_context *ctx); + +/** + * \brief Obtain a copy of the MAC on additional authenticated data. + * + * This function may be called only after `br_eax_flip()`; it copies the + * AAD-specific MAC value into the provided state. The MAC value depends + * on the secret key and the additional data itself, but not on the + * nonce. The updated state `st` is meant to be used as parameter for a + * further `br_eax_reset_post_aad()` call. + * + * \param ctx EAX context structure. + * \param st captured state to update. + */ +static inline void +br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st) +{ + memcpy(st->st[1], ctx->head, sizeof ctx->head); +} + +/** + * \brief Encrypt or decrypt some data with EAX. + * + * Data encryption or decryption can be done after `br_eax_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param ctx EAX context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute EAX authentication tag. + * + * Compute the EAX authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * EAX run: no data may be processed with that EAX context afterwards, + * until `br_eax_reset()` is called to initiate a new EAX run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_eax_get_tag(br_eax_context *ctx, void *tag); + +/** + * \brief Compute and check EAX authentication tag. + * + * This function is an alternative to `br_eax_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag); + +/** + * \brief Compute EAX authentication tag (with truncation). + * + * This function is similar to `br_eax_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the EAX run: no data may be processed with that EAX context + * afterwards, until `br_eax_reset()` is called to initiate a new EAX + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check EAX authentication tag (with truncation). + * + * This function is an alternative to `br_eax_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag_trunc(br_eax_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for EAX. + */ +extern const br_aead_class br_eax_vtable; + +/** + * \brief Context structure for CCM. + * + * CCM is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with CCM + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The authentication tag length, and plaintext length, MUST be + * known when starting processing data. Plaintext and ciphertext + * can still be provided by chunks, but the total size must match + * the value provided upon initialisation. + * + * - The nonce length is constrained between 7 and 13 bytes (inclusive). + * Furthermore, the plaintext length, when encoded, must fit over + * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then + * the plaintext length cannot exceed 65535 bytes. + * + * - Additional authenticated data length is practically unlimited + * (formal limit is at 2^64 bytes). + * + * - The authentication tag has length 4 to 16 bytes (even values only). + * + * The CCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * CCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char tagmask[16]; + unsigned char buf[16]; + size_t ptr; + size_t tag_len; +#endif +} br_ccm_context; + +/** + * \brief Initialize a CCM context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the CCM context. + * + * After this function has been called, the `br_ccm_reset()` function must + * be called, to provide the nonce for CCM computation. + * + * \param ctx CCM context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Reset a CCM context. + * + * This function resets an already initialised CCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing CCM computation that + * uses the provided context structure. + * + * The `aad_len` parameter contains the total length, in bytes, of the + * additional authenticated data. It may be zero. That length MUST be + * exact. + * + * The `data_len` parameter contains the total length, in bytes, of the + * data that will be injected (plaintext or ciphertext). That length MUST + * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)). + * + * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range + * (inclusive). + * + * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and + * be an even integer. Short tags mechanically allow for higher forgery + * probabilities; hence, tag sizes smaller than 12 bytes shall be used only + * with care. + * + * It is critical to CCM security that nonce values are not repeated for + * the same encryption key. Random generation of nonces is not generally + * recommended, due to the relatively small maximum nonce value. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the tag or nonce length is out of range, or if the + * plaintext/ciphertext length cannot be encoded with the specified + * nonce length. + * + * \param ctx CCM context structure. + * \param nonce CCM nonce to use. + * \param nonce_len CCM nonce length (in bytes, 7 to 13). + * \param aad_len additional authenticated data length (in bytes). + * \param data_len plaintext/ciphertext length (in bytes). + * \param tag_len tag length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, + uint64_t aad_len, uint64_t data_len, size_t tag_len); + +/** + * \brief Inject additional authenticated data into CCM. + * + * The provided data is injected into a running CCM computation. Additional + * data must be injected _before_ the call to `br_ccm_flip()`. + * Additional data can be injected in several chunks of arbitrary length, + * but the total amount MUST exactly match the value which was provided + * to `br_ccm_reset()`. + * + * \param ctx CCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into CCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_ccm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx CCM context structure. + */ +void br_ccm_flip(br_ccm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with CCM. + * + * Data encryption or decryption can be done after `br_ccm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length, provided + * that the total length exactly matches the length provided to the + * `br_ccm_reset()` call. + * + * \param ctx CCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute CCM authentication tag. + * + * Compute the CCM authentication tag. This call terminates the CCM + * run: all data must have been injected with `br_ccm_run()` (in zero, + * one or more successive calls). After this function has been called, + * no more data can br processed; a `br_ccm_reset()` call is required + * to start a new message. + * + * The tag length was provided upon context initialisation (last call + * to `br_ccm_reset()`); it is returned by this function. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_ccm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx CCM context structure. + * \param tag destination buffer for the tag (up to 16 bytes). + * \return the tag length (in bytes). + */ +size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag); + +/** + * \brief Compute and check CCM authentication tag. + * + * This function is an alternative to `br_ccm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx CCM context structure. + * \param tag tag value to compare with (up to 16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_block.h b/template/sysroot/include/bearssl_block.h new file mode 100644 index 0000000..683a490 --- /dev/null +++ b/template/sysroot/include/bearssl_block.h @@ -0,0 +1,2618 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_BLOCK_H__ +#define BR_BEARSSL_BLOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_block.h + * + * # Block Ciphers and Symmetric Ciphers + * + * This file documents the API for block ciphers and other symmetric + * ciphers. + * + * + * ## Procedural API + * + * For a block cipher implementation, up to three separate sets of + * functions are provided, for CBC encryption, CBC decryption, and CTR + * encryption/decryption. Each set has its own context structure, + * initialised with the encryption key. + * + * For CBC encryption and decryption, the data to encrypt or decrypt is + * referenced as a sequence of blocks. The implementations assume that + * there is no partial block; no padding is applied or removed. The + * caller is responsible for handling any kind of padding. + * + * Function for CTR encryption are defined only for block ciphers with + * blocks of 16 bytes or more (i.e. AES, but not DES/3DES). + * + * Each implemented block cipher is identified by an "internal name" + * from which are derived the names of structures and functions that + * implement the cipher. For the block cipher of internal name "`xxx`", + * the following are defined: + * + * - `br_xxx_BLOCK_SIZE` + * + * A macro that evaluates to the block size (in bytes) of the + * cipher. For all implemented block ciphers, this value is a + * power of two. + * + * - `br_xxx_cbcenc_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC encryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC encryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)` + * + * Perform CBC encryption of `len` bytes, in place. The encrypted data + * replaces the cleartext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last encrypted block. + * + * - `br_xxx_cbcdec_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC decryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC decryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)` + * + * Perform CBC decryption of `len` bytes, in place. The decrypted data + * replaces the ciphertext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last _encrypted_ block. + * + * - `br_xxx_ctr_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CTR encryption and + * decryption. The structure first field is called `vtable` and + * points to the appropriate OOP structure. + * + * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CTR encryption and decryption + * are computed and written in the provided context structure. The + * key length MUST be adequate for the implemented block cipher. This + * function also sets the `vtable` field. + * + * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`) + * + * Perform CTR encryption/decryption of some data. Processing is done + * "in place" (the output data replaces the input data). This function + * implements the "standard incrementing function" from NIST SP800-38A, + * annex B: the IV length shall be 4 bytes less than the block size + * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting + * with `cc`. The data length (`len`) is not necessarily a multiple of + * the block size. The new counter value is returned, which supports + * chunked processing, provided that each chunk length (except possibly + * the last one) is a multiple of the block size. + * + * - `br_xxx_ctrcbc_keys` + * + * Context structure that contains the subkeys resulting from the + * key expansion. These subkeys are appropriate for doing combined + * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX + * authenticated encryption modes. The structure first field is + * called `vtable` and points to the appropriate OOP structure. + * + * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for combined CTR + * encryption/decryption and CBC-MAC are computed and written in the + * provided context structure. The key length MUST be adequate for + * the implemented block cipher. This function also sets the + * `vtable` field. + * + * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR encryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR encryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (output of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR decryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR decryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (input of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)` + * + * Perform CTR encryption or decryption of the provided data. The + * data is processed "in place" (the output data replaces the input + * data). A full block-sized counter is applied (i.e. for 128-bit + * blocks, the counter is incremented as a 128-bit value). The 'ctr' + * array contains the initial value for the counter (used in the + * first block), and it is updated with the new value after data + * processing. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)` + * + * Compute CBC-MAC over the provided data. The IV for CBC-MAC is + * provided as 'cbcmac'; the output is written over the same array. + * The data itself is untouched. The data length MUST be a multiple + * of the block size. + * + * + * It shall be noted that the key expansion functions return `void`. If + * the provided key length is not allowed, then there will be no error + * reporting; implementations need not validate the key length, thus an + * invalid key length may result in undefined behaviour (e.g. buffer + * overflow). + * + * Subkey structures contain no interior pointer, and no external + * resources are allocated upon key expansion. They can thus be + * discarded without any explicit deallocation. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `run` + * + * Pointer to the encryption/decryption function. + * + * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly + * different structure: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `encrypt` + * + * Pointer to the CTR encryption + CBC-MAC function. + * + * - `decrypt` + * + * Pointer to the CTR decryption + CBC-MAC function. + * + * - `ctr` + * + * Pointer to the CTR encryption/decryption function. + * + * - `mac` + * + * Pointer to the CBC-MAC function. + * + * For block cipher "`xxx`", static, constant instances of these + * structures are defined, under the names: + * + * - `br_xxx_cbcenc_vtable` + * - `br_xxx_cbcdec_vtable` + * - `br_xxx_ctr_vtable` + * - `br_xxx_ctrcbc_vtable` + * + * + * ## Implemented Block Ciphers + * + * Provided implementations are: + * + * | Name | Function | Block Size (bytes) | Key lengths (bytes) | + * | :-------- | :------- | :----------------: | :-----------------: | + * | aes_big | AES | 16 | 16, 24 and 32 | + * | aes_small | AES | 16 | 16, 24 and 32 | + * | aes_ct | AES | 16 | 16, 24 and 32 | + * | aes_ct64 | AES | 16 | 16, 24 and 32 | + * | aes_x86ni | AES | 16 | 16, 24 and 32 | + * | aes_pwr8 | AES | 16 | 16, 24 and 32 | + * | des_ct | DES/3DES | 8 | 8, 16 and 24 | + * | des_tab | DES/3DES | 8 | 8, 16 and 24 | + * + * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8, + * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so + * the _effective_ key lengths, from a security point of view, are 56, + * 112 and 168 bits, respectively. + * + * `aes_big` is a "classical" AES implementation, using tables. It + * is fast but not constant-time, since it makes data-dependent array + * accesses. + * + * `aes_small` is an AES implementation optimized for code size. It + * is substantially slower than `aes_big`; it is not constant-time + * either. + * + * `aes_ct` is a constant-time implementation of AES; its code is about + * as big as that of `aes_big`, while its performance is comparable to + * that of `aes_small`. However, it is constant-time. This + * implementation should thus be considered to be the "default" AES in + * BearSSL, to be used unless the operational context guarantees that a + * non-constant-time implementation is safe, or an architecture-specific + * constant-time implementation can be used (e.g. using dedicated + * hardware opcodes). + * + * `aes_ct64` is another constant-time implementation of AES. It is + * similar to `aes_ct` but uses 64-bit values. On 32-bit machines, + * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has + * a larger footprint; however, on 64-bit architectures, `aes_ct64` + * is typically twice faster than `aes_ct` for modes that allow parallel + * operations (i.e. CTR, and CBC decryption, but not CBC encryption). + * + * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It + * uses the AES-NI opcodes when available. + * + * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and + * 64-bit, both little-endian and big-endian). It uses the AES opcodes + * present in POWER8 and later. + * + * `des_tab` is a classic, table-based implementation of DES/3DES. It + * is not constant-time. + * + * `des_ct` is an constant-time implementation of DES/3DES. It is + * substantially slower than `des_tab`. + * + * ## ChaCha20 and Poly1305 + * + * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They + * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539). + * + * Two function pointer types are defined: + * + * - `br_chacha20_run` describes a function that implements ChaCha20 + * only. + * + * - `br_poly1305_run` describes an implementation of Poly1305, + * in the AEAD combination with ChaCha20 specified in RFC 7539 + * (the ChaCha20 implementation is provided as a function pointer). + * + * `chacha20_ct` is a straightforward implementation of ChaCha20 in + * plain C; it is constant-time, small, and reasonably fast. + * + * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that + * support these opcodes). It is faster than `chacha20_ct`. + * + * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD + * construction, where the Poly1305 part is performed with mixed 32-bit + * multiplications (operands are 32-bit, result is 64-bit). + * + * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit + * multiplications (32-bit operands, 32-bit result). It is slower than + * `poly1305_ctmul`, except on some specific architectures such as + * the ARM Cortex M0+. + * + * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit + * multiplications (operands are 64-bit, result is 128-bit) on 64-bit + * platforms that support such operations. + * + * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15" + * big integer implementation. It is meant mostly for testing purposes, + * although it can help with saving a few hundred bytes of code footprint + * on systems where code size is scarce. + */ + +/** + * \brief Class type for CBC encryption implementations. + * + * A `br_block_cbcenc_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for encrypting data. + */ +typedef struct br_block_cbcenc_class_ br_block_cbcenc_class; +struct br_block_cbcenc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcenc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC encryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is encrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC encryption (updated). + * \param data data to encrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcenc_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CBC decryption implementations. + * + * A `br_block_cbcdec_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for decrypting data. + */ +typedef struct br_block_cbcdec_class_ br_block_cbcdec_class; +struct br_block_cbcdec_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcdec_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC decryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is decrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC decryption (updated). + * \param data data to decrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcdec_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CTR encryption/decryption implementations. + * + * A `br_block_ctr_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data. + */ +typedef struct br_block_ctr_class_ br_block_ctr_class; +struct br_block_ctr_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctr_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption or decryption. + * + * The `iv` parameter points to the IV for this run; its + * length is exactly 4 bytes less than the block size (e.g. + * 12 bytes for AES/CTR). The IV is combined with a 32-bit + * block counter to produce the block value which is processed + * with the block cipher. + * + * The data to encrypt or decrypt is updated "in place". Its + * length (`len` bytes) is not required to be a multiple of + * the block size; if the final block is partial, then the + * corresponding key stream bits are dropped. + * + * The resulting counter value is returned. + * + * \param ctx context structure (already initialised). + * \param iv IV for CTR encryption/decryption. + * \param cc initial value for the block counter. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \return the new block counter value. + */ + uint32_t (*run)(const br_block_ctr_class *const *ctx, + const void *iv, uint32_t cc, void *data, size_t len); +}; + +/** + * \brief Class type for combined CTR and CBC-MAC implementations. + * + * A `br_block_ctrcbc_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data, along with CBC-MAC. + */ +typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class; +struct br_block_ctrcbc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctrcbc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as encryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (output of CTR + * encryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to encrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to encrypt. + * \param len data length (in bytes). + */ + void (*encrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR decryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*decrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR encryption/decryption only. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*ctr)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *data, size_t len); + + /** + * \brief Run the CBC-MAC only. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data is unmodified. Its length (`len` bytes) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*mac)(const br_block_ctrcbc_class *const *ctx, + void *cbcmac, const void *data, size_t len); +}; + +/* + * Traditional, table-based AES implementation. It is fast, but uses + * internal tables (in particular a 1 kB table for encryption, another + * 1 kB table for decryption, and a 256-byte table for key schedule), + * and it is not constant-time. In contexts where cache-timing attacks + * apply, this implementation may leak the secret key. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_big_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_big` implementation). + */ +extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_big` implementation). + */ +extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_big` implementation). + */ +extern const br_block_ctr_class br_aes_big_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_big` implementation). + */ +extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to encrypt or decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation optimized for size. It is slower than the + * traditional table-based AES implementation, but requires much less + * code. It still uses data-dependent table accesses (albeit within a + * much smaller 256-byte table), which makes it conceptually vulnerable + * to cache-timing attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_small_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_small` implementation). + */ +extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_small` implementation). + */ +extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_small` implementation). + */ +extern const br_block_ctr_class br_aes_small_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_small` implementation). + */ +extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * Constant-time AES implementation. Its size is similar to that of + * 'aes_big', and its performance is similar to that of 'aes_small' (faster + * decryption, slower encryption). However, it is constant-time, i.e. + * immune to cache-timing and similar attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct` implementation). + */ +extern const br_block_ctr_class br_aes_ct_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * 64-bit constant-time AES implementation. It is similar to 'aes_ct' + * but uses 64-bit registers, making it about twice faster than 'aes_ct' + * on 64-bit platforms, while remaining constant-time and with a similar + * code size. (The doubling in performance is only for CBC decryption + * and CTR mode; CBC encryption is non-parallel and cannot benefit from + * the larger registers.) + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct64_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct64` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct64` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct64` implementation). + */ +extern const br_block_ctr_class br_aes_ct64_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct64` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation using AES-NI opcodes (x86 platform). + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_x86ni_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void); + +/* + * AES implementation using POWER8 opcodes. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_pwr8_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_pwr8_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that + * implementation was compiled in the library _and_ the POWER8 crypto + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void); + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all AES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_aes_big_cbcenc_keys c_big; + br_aes_small_cbcenc_keys c_small; + br_aes_ct_cbcenc_keys c_ct; + br_aes_ct64_cbcenc_keys c_ct64; + br_aes_x86ni_cbcenc_keys c_x86ni; + br_aes_pwr8_cbcenc_keys c_pwr8; +} br_aes_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all AES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_aes_big_cbcdec_keys c_big; + br_aes_small_cbcdec_keys c_small; + br_aes_ct_cbcdec_keys c_ct; + br_aes_ct64_cbcdec_keys c_ct64; + br_aes_x86ni_cbcdec_keys c_x86ni; + br_aes_pwr8_cbcdec_keys c_pwr8; +} br_aes_gen_cbcdec_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption and decryption) for all AES implementations. + */ +typedef union { + const br_block_ctr_class *vtable; + br_aes_big_ctr_keys c_big; + br_aes_small_ctr_keys c_small; + br_aes_ct_ctr_keys c_ct; + br_aes_ct64_ctr_keys c_ct64; + br_aes_x86ni_ctr_keys c_x86ni; + br_aes_pwr8_ctr_keys c_pwr8; +} br_aes_gen_ctr_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations. + */ +typedef union { + const br_block_ctrcbc_class *vtable; + br_aes_big_ctrcbc_keys c_big; + br_aes_small_ctrcbc_keys c_small; + br_aes_ct_ctrcbc_keys c_ct; + br_aes_ct64_ctrcbc_keys c_ct64; + br_aes_x86ni_ctrcbc_keys c_x86ni; + br_aes_pwr8_ctrcbc_keys c_pwr8; +} br_aes_gen_ctrcbc_keys; + +/* + * Traditional, table-based implementation for DES/3DES. Since tables are + * used, cache-timing attacks are conceptually possible. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_tab_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_tab` implementation). + */ +extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_tab` implementation). + */ +extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * Constant-time implementation for DES/3DES. It is substantially slower + * (by a factor of about 4x), but also immune to cache-timing attacks. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_ct_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_ct` implementation). + */ +extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_ct` implementation). + */ +extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * These structures are large enough to accommodate subkeys for all + * DES/3DES implementations. + */ + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all DES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_des_tab_cbcenc_keys tab; + br_des_ct_cbcenc_keys ct; +} br_des_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all DES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_des_tab_cbcdec_keys c_tab; + br_des_ct_cbcdec_keys c_ct; +} br_des_gen_cbcdec_keys; + +/** + * \brief Type for a ChaCha20 implementation. + * + * An implementation follows the description in RFC 7539: + * + * - Key is 256 bits (`key` points to exactly 32 bytes). + * + * - IV is 96 bits (`iv` points to exactly 12 bytes). + * + * - Block counter is over 32 bits and starts at value `cc`; the + * resulting value is returned. + * + * Data (pointed to by `data`, of length `len`) is encrypted/decrypted + * in place. If `len` is not a multiple of 64, then the excess bytes from + * the last block processing are dropped (therefore, "chunked" processing + * works only as long as each non-final chunk has a length multiple of 64). + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +typedef uint32_t (*br_chacha20_run)(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (straightforward C code, constant-time). + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_ct_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (SSE2 code, constant-time). + * + * This implementation is available only on x86 platforms, depending on + * compiler support. Moreover, in 32-bit mode, it might not actually run, + * if the underlying hardware does not implement the SSE2 opcode (in + * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled + * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain + * a pointer to that function. + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_sse2_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief Obtain the `sse2` ChaCha20 implementation, if available. + * + * This function returns a pointer to `br_chacha20_sse2_run`, if + * that implementation was compiled in the library _and_ the SSE2 + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `0`. + * + * \return the `sse2` ChaCha20 implementation, or `0`. + */ +br_chacha20_run br_chacha20_sse2_get(void); + +/** + * \brief Type for a ChaCha20+Poly1305 AEAD implementation. + * + * The provided data is encrypted or decrypted with ChaCha20. The + * authentication tag is computed on the concatenation of the + * additional data and the ciphertext, with the padding and lengths + * as described in RFC 7539 (section 2.8). + * + * After decryption, the caller is responsible for checking that the + * computed tag matches the expected value. + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +typedef void (*br_poly1305_run)(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul32_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (i15). + * + * This implementation relies on the generic big integer code "i15" + * (which uses pure 32-bit multiplications). As such, it may save a + * little code footprint in a context where "i15" is already included + * (e.g. for elliptic curves or for RSA); however, it is also + * substantially slower than the ctmul and ctmul32 implementations. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_i15_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq). + * + * This implementation uses 64-bit multiplications (result over 128 bits). + * It is available only on platforms that offer such a primitive (in + * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to + * dynamically obtain a pointer to that function, or 0 if not supported. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmulq_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available. + * + * This function returns a pointer to the `br_poly1305_ctmulq_run()` + * function if supported on the current platform; otherwise, it returns 0. + * + * \return the ctmulq ChaCha20+Poly1305 implementation, or 0. + */ +br_poly1305_run br_poly1305_ctmulq_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_ec.h b/template/sysroot/include/bearssl_ec.h new file mode 100644 index 0000000..acd3a2b --- /dev/null +++ b/template/sysroot/include/bearssl_ec.h @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_EC_H__ +#define BR_BEARSSL_EC_H__ + +#include +#include + +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ec.h + * + * # Elliptic Curves + * + * This file documents the EC implementations provided with BearSSL, and + * ECDSA. + * + * ## Elliptic Curve API + * + * Only "named curves" are supported. Each EC implementation supports + * one or several named curves, identified by symbolic identifiers. + * These identifiers are small integers, that correspond to the values + * registered by the + * [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8). + * + * Since all currently defined elliptic curve identifiers are in the 0..31 + * range, it is convenient to encode support of some curves in a 32-bit + * word, such that bit x corresponds to curve of identifier x. + * + * An EC implementation is incarnated by a `br_ec_impl` instance, that + * offers the following fields: + * + * - `supported_curves` + * + * A 32-bit word that documents the identifiers of the curves supported + * by this implementation. + * + * - `generator()` + * + * Callback method that returns a pointer to the conventional generator + * point for that curve. + * + * - `order()` + * + * Callback method that returns a pointer to the subgroup order for + * that curve. That value uses unsigned big-endian encoding. + * + * - `xoff()` + * + * Callback method that returns the offset and length of the X + * coordinate in an encoded point. + * + * - `mul()` + * + * Multiply a curve point with an integer. + * + * - `mulgen()` + * + * Multiply the curve generator with an integer. This may be faster + * than the generic `mul()`. + * + * - `muladd()` + * + * Multiply two curve points by two integers, and return the sum of + * the two products. + * + * All curve points are represented in uncompressed format. The `mul()` + * and `muladd()` methods take care to validate that the provided points + * are really part of the relevant curve subgroup. + * + * For all point multiplication functions, the following holds: + * + * - Functions validate that the provided points are valid members + * of the relevant curve subgroup. An error is reported if that is + * not the case. + * + * - Processing is constant-time, even if the point operands are not + * valid. This holds for both the source and resulting points, and + * the multipliers (integers). Only the byte length of the provided + * multiplier arrays (not their actual value length in bits) may + * leak through timing-based side channels. + * + * - The multipliers (integers) MUST be lower than the subgroup order. + * If this property is not met, then the result is indeterminate, + * but an error value is not necessarily returned. + * + * + * ## ECDSA + * + * ECDSA signatures have two standard formats, called "raw" and "asn1". + * Internally, such a signature is a pair of modular integers `(r,s)`. + * The "raw" format is the concatenation of the unsigned big-endian + * encodings of these two integers, possibly left-padded with zeros so + * that they have the same encoded length. The "asn1" format is the + * DER encoding of an ASN.1 structure that contains the two integer + * values: + * + * ECDSASignature ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * In general, in all of X.509 and SSL/TLS, the "asn1" format is used. + * BearSSL offers ECDSA implementations for both formats; conversion + * functions between the two formats are also provided. Conversion of a + * "raw" format signature into "asn1" may enlarge a signature by no more + * than 9 bytes for all supported curves; conversely, conversion of an + * "asn1" signature to "raw" may expand the signature but the "raw" + * length will never be more than twice the length of the "asn1" length + * (and usually it will be shorter). + * + * Note that for a given signature, the "raw" format is not fully + * deterministic, in that it does not enforce a minimal common length. + */ + +/* + * Standard curve ID. These ID are equal to the assigned numerical + * identifiers assigned to these curves for TLS: + * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + */ + +/** \brief Identifier for named curve sect163k1. */ +#define BR_EC_sect163k1 1 + +/** \brief Identifier for named curve sect163r1. */ +#define BR_EC_sect163r1 2 + +/** \brief Identifier for named curve sect163r2. */ +#define BR_EC_sect163r2 3 + +/** \brief Identifier for named curve sect193r1. */ +#define BR_EC_sect193r1 4 + +/** \brief Identifier for named curve sect193r2. */ +#define BR_EC_sect193r2 5 + +/** \brief Identifier for named curve sect233k1. */ +#define BR_EC_sect233k1 6 + +/** \brief Identifier for named curve sect233r1. */ +#define BR_EC_sect233r1 7 + +/** \brief Identifier for named curve sect239k1. */ +#define BR_EC_sect239k1 8 + +/** \brief Identifier for named curve sect283k1. */ +#define BR_EC_sect283k1 9 + +/** \brief Identifier for named curve sect283r1. */ +#define BR_EC_sect283r1 10 + +/** \brief Identifier for named curve sect409k1. */ +#define BR_EC_sect409k1 11 + +/** \brief Identifier for named curve sect409r1. */ +#define BR_EC_sect409r1 12 + +/** \brief Identifier for named curve sect571k1. */ +#define BR_EC_sect571k1 13 + +/** \brief Identifier for named curve sect571r1. */ +#define BR_EC_sect571r1 14 + +/** \brief Identifier for named curve secp160k1. */ +#define BR_EC_secp160k1 15 + +/** \brief Identifier for named curve secp160r1. */ +#define BR_EC_secp160r1 16 + +/** \brief Identifier for named curve secp160r2. */ +#define BR_EC_secp160r2 17 + +/** \brief Identifier for named curve secp192k1. */ +#define BR_EC_secp192k1 18 + +/** \brief Identifier for named curve secp192r1. */ +#define BR_EC_secp192r1 19 + +/** \brief Identifier for named curve secp224k1. */ +#define BR_EC_secp224k1 20 + +/** \brief Identifier for named curve secp224r1. */ +#define BR_EC_secp224r1 21 + +/** \brief Identifier for named curve secp256k1. */ +#define BR_EC_secp256k1 22 + +/** \brief Identifier for named curve secp256r1. */ +#define BR_EC_secp256r1 23 + +/** \brief Identifier for named curve secp384r1. */ +#define BR_EC_secp384r1 24 + +/** \brief Identifier for named curve secp521r1. */ +#define BR_EC_secp521r1 25 + +/** \brief Identifier for named curve brainpoolP256r1. */ +#define BR_EC_brainpoolP256r1 26 + +/** \brief Identifier for named curve brainpoolP384r1. */ +#define BR_EC_brainpoolP384r1 27 + +/** \brief Identifier for named curve brainpoolP512r1. */ +#define BR_EC_brainpoolP512r1 28 + +/** \brief Identifier for named curve Curve25519. */ +#define BR_EC_curve25519 29 + +/** \brief Identifier for named curve Curve448. */ +#define BR_EC_curve448 30 + +/** + * \brief Structure for an EC public key. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Public curve point (uncompressed format). */ + unsigned char *q; + /** \brief Length of public curve point (in bytes). */ + size_t qlen; +} br_ec_public_key; + +/** + * \brief Structure for an EC private key. + * + * The private key is an integer modulo the curve subgroup order. The + * encoding below tolerates extra leading zeros. In general, it is + * recommended that the private key has the same length as the curve + * subgroup order. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Private key (integer, unsigned big-endian encoding). */ + unsigned char *x; + /** \brief Private key length (in bytes). */ + size_t xlen; +} br_ec_private_key; + +/** + * \brief Type for an EC implementation. + */ +typedef struct { + /** + * \brief Supported curves. + * + * This word is a bitfield: bit `x` is set if the curve of ID `x` + * is supported. E.g. an implementation supporting both NIST P-256 + * (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have + * value `0x01800000` in this field. + */ + uint32_t supported_curves; + + /** + * \brief Get the conventional generator. + * + * This function returns the conventional generator (encoded + * curve point) for the specified curve. This function MUST NOT + * be called if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded generator length (in bytes). + * \return the encoded generator. + */ + const unsigned char *(*generator)(int curve, size_t *len); + + /** + * \brief Get the subgroup order. + * + * This function returns the order of the subgroup generated by + * the conventional generator, for the specified curve. Unsigned + * big-endian encoding is used. This function MUST NOT be called + * if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded order length (in bytes). + * \return the encoded order. + */ + const unsigned char *(*order)(int curve, size_t *len); + + /** + * \brief Get the offset and length for the X coordinate. + * + * This function returns the offset and length (in bytes) of + * the X coordinate in an encoded non-zero point. + * + * \param curve curve identifier. + * \param len receiver for the X coordinate length (in bytes). + * \return the offset for the X coordinate (in bytes). + */ + size_t (*xoff)(int curve, size_t *len); + + /** + * \brief Multiply a curve point by an integer. + * + * The source point is provided in array `G` (of size `Glen` bytes); + * the multiplication result is written over it. The multiplier + * `x` (of size `xlen` bytes) uses unsigned big-endian encoding. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source point must be a valid point on the relevant curve + * subgroup (and not the "point at infinity" either). If this is + * not the case, then this function returns an error (0). + * + * - The multiplier integer MUST be non-zero and less than the + * curve subgroup order. If this property does not hold, then + * the result is indeterminate and an error code is not + * guaranteed. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `G` are indeterminate. + * + * \param G point to multiply. + * \param Glen length of the encoded point (in bytes). + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*mul)(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply the generator by an integer. + * + * The multiplier MUST be non-zero and less than the curve + * subgroup order. Results are indeterminate if this property + * does not hold. + * + * \param R output buffer for the point. + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return encoded result point length (in bytes). + */ + size_t (*mulgen)(unsigned char *R, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply two points by two integers and add the + * results. + * + * The point `x*A + y*B` is computed and written back in the `A` + * array. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source points (`A` and `B`) must be valid points on + * the relevant curve subgroup (and not the "point at + * infinity" either). If this is not the case, then this + * function returns an error (0). + * + * - If the `B` pointer is `NULL`, then the conventional + * subgroup generator is used. With some implementations, + * this may be faster than providing a pointer to the + * generator. + * + * - The multiplier integers (`x` and `y`) MUST be non-zero + * and less than the curve subgroup order. If either integer + * is zero, then an error is reported, but if one of them is + * not lower than the subgroup order, then the result is + * indeterminate and an error code is not guaranteed. + * + * - If the final result is the point at infinity, then an + * error is returned. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `A` are indeterminate. + * + * \param A first point to multiply. + * \param B second point to multiply (`NULL` for the generator). + * \param len common length of the encoded points (in bytes). + * \param x multiplier for `A` (unsigned big-endian). + * \param xlen length of multiplier for `A` (in bytes). + * \param y multiplier for `A` (unsigned big-endian). + * \param ylen length of multiplier for `A` (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve); +} br_ec_impl; + +/** + * \brief EC implementation "i31". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 31-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i31; + +/** + * \brief EC implementation "i15". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 15-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i15; + +/** + * \brief EC implementation "m15" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), with optional Karatsuba decomposition, and fast + * modular reduction thanks to the field modulus special format. Only + * 32-bit multiplications are used (with 32-bit results, not 64-bit). + */ +extern const br_ec_impl br_ec_p256_m15; + +/** + * \brief EC implementation "m31" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), relying on multiplications of 31-bit values + * (MUL31). + */ +extern const br_ec_impl br_ec_p256_m31; + +/** + * \brief EC implementation "m62" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m62; + +/** + * \brief Get the "m62" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m64; + +/** + * \brief Get the "m64" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m64_get(void); + +/** + * \brief EC implementation "i15" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 15-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i15; + +/** + * \brief EC implementation "i31" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 31-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i31; + +/** + * \brief EC implementation "m15" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 15 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m15; + +/** + * \brief EC implementation "m31" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 31 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m31; + +/** + * \brief EC implementation "m62" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 62 bits, with a 124-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m62; + +/** + * \brief Get the "m62" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m64; + +/** + * \brief Get the "m64" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m64_get(void); + +/** + * \brief Aggregate EC implementation "m15". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m15` for Curve25519 + * - `br_ec_p256_m15` for NIST P-256 + * - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m15; + +/** + * \brief Aggregate EC implementation "m31". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m31` for Curve25519 + * - `br_ec_p256_m31` for NIST P-256 + * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m31; + +/** + * \brief Get the "default" EC implementation for the current system. + * + * This returns a pointer to the preferred implementation on the + * current system. + * + * \return the default EC implementation. + */ +const br_ec_impl *br_ec_get_default(void); + +/** + * \brief Convert a signature from "raw" to "asn1". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but by no more than 9 bytes at + * most. On error, 0 is returned (error conditions include an odd raw + * signature length, or an oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len); + +/** + * \brief Convert a signature from "asn1" to "raw". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but the new signature length + * will be less than twice the source length at most. On error, 0 is + * returned (error conditions include an invalid ASN.1 structure or an + * oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len); + +/** + * \brief Type for an ECDSA signer function. + * + * A pointer to the EC implementation is provided. The hash value is + * assumed to have the length inferred from the designated hash function + * class. + * + * Signature is written in the buffer pointed to by `sig`, and the length + * (in bytes) is returned. On error, nothing is written in the buffer, + * and 0 is returned. This function returns 0 if the specified curve is + * not supported by the provided EC implementation. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation; maximum length is predictable from the implemented + * curve: + * + * | curve | raw | asn1 | + * | :--------- | --: | ---: | + * | NIST P-256 | 64 | 72 | + * | NIST P-384 | 96 | 104 | + * | NIST P-521 | 132 | 139 | + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief Type for an ECDSA signature verification function. + * + * A pointer to the EC implementation is provided. The hashed value, + * computed over the purportedly signed data, is also provided with + * its length. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation. + * + * Returned value is 1 on success (valid signature), 0 on error. This + * function returns 0 if the specified curve is not supported by the + * provided EC implementation. + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i31" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i15" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief Get "default" ECDSA implementation (signer, asn1 format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (signer, raw format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, asn1 format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, raw format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); + +/** + * \brief Maximum size for EC private key element buffer. + * + * This is the largest number of bytes that `br_ec_keygen()` may need or + * ever return. + */ +#define BR_EC_KBUF_PRIV_MAX_SIZE 72 + +/** + * \brief Maximum size for EC public key element buffer. + * + * This is the largest number of bytes that `br_ec_compute_public()` may + * need or ever return. + */ +#define BR_EC_KBUF_PUB_MAX_SIZE 145 + +/** + * \brief Generate a new EC private key. + * + * If the specified `curve` is not supported by the elliptic curve + * implementation (`impl`), then this function returns zero. + * + * The `sk` structure fields are set to the new private key data. In + * particular, `sk.x` is made to point to the provided key buffer (`kbuf`), + * in which the actual private key data is written. That buffer is assumed + * to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum + * size for all supported curves. + * + * The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then + * the private key is not actually generated, and `sk` may also be `NULL`; + * the minimum length for `kbuf` is still computed and returned. + * + * If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is + * still generated and stored in `kbuf`. + * + * \param rng_ctx source PRNG context (already initialized). + * \param impl the elliptic curve implementation. + * \param sk the private key structure to fill, or `NULL`. + * \param kbuf the key element buffer, or `NULL`. + * \param curve the curve identifier. + * \return the key data length (in bytes), or zero. + */ +size_t br_ec_keygen(const br_prng_class **rng_ctx, + const br_ec_impl *impl, br_ec_private_key *sk, + void *kbuf, int curve); + +/** + * \brief Compute EC public key from EC private key. + * + * This function uses the provided elliptic curve implementation (`impl`) + * to compute the public key corresponding to the private key held in `sk`. + * The public key point is written into `kbuf`, which is then linked from + * the `*pk` structure. The size of the public key point, i.e. the number + * of bytes used in `kbuf`, is returned. + * + * If `kbuf` is `NULL`, then the public key point is NOT computed, and + * the public key structure `*pk` is unmodified (`pk` may be `NULL` in + * that case). The size of the public key point is still returned. + * + * If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key + * point is computed and stored in `kbuf`, and its size is returned. + * + * If the curve used by the private key is not supported by the curve + * implementation, then this function returns zero. + * + * The private key MUST be valid. An off-range private key value is not + * necessarily detected, and leads to unpredictable results. + * + * \param impl the elliptic curve implementation. + * \param pk the public key structure to fill (or `NULL`). + * \param kbuf the public key point buffer (or `NULL`). + * \param sk the source private key. + * \return the public key point length (in bytes), or zero. + */ +size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, + void *kbuf, const br_ec_private_key *sk); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_hash.h b/template/sysroot/include/bearssl_hash.h new file mode 100644 index 0000000..ca4fa26 --- /dev/null +++ b/template/sysroot/include/bearssl_hash.h @@ -0,0 +1,1346 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HASH_H__ +#define BR_BEARSSL_HASH_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hash.h + * + * # Hash Functions + * + * This file documents the API for hash functions. + * + * + * ## Procedural API + * + * For each implemented hash function, of name "`xxx`", the following + * elements are defined: + * + * - `br_xxx_vtable` + * + * An externally defined instance of `br_hash_class`. + * + * - `br_xxx_SIZE` + * + * A macro that evaluates to the output size (in bytes) of the + * hash function. + * + * - `br_xxx_ID` + * + * A macro that evaluates to a symbolic identifier for the hash + * function. Such identifiers are used with HMAC and signature + * algorithm implementations. + * + * NOTE: for the "standard" hash functions defined in [the TLS + * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1), + * the symbolic identifiers match the constants used in TLS, i.e. + * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, + * respectively. + * + * - `br_xxx_context` + * + * Context for an ongoing computation. It is allocated by the + * caller, and a pointer to it is passed to all functions. A + * context contains no interior pointer, so it can be moved around + * and cloned (with a simple `memcpy()` or equivalent) in order to + * capture the function state at some point. Computations that use + * distinct context structures are independent of each other. The + * first field of `br_xxx_context` is always a pointer to the + * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer. + * + * - `br_xxx_init(br_xxx_context *ctx)` + * + * Initialise the provided context. Previous contents of the structure + * are ignored. This calls resets the context to the start of a new + * hash computation; it also sets the first field of the context + * structure (called `vtable`) to a pointer to the statically + * allocated constant `br_xxx_vtable` structure. + * + * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)` + * + * Add some more bytes to the hash computation represented by the + * provided context. + * + * - `br_xxx_out(const br_xxx_context *ctx, void *out)` + * + * Complete the hash computation and write the result in the provided + * buffer. The output buffer MUST be large enough to accommodate the + * result. The context is NOT modified by this operation, so this + * function can be used to get a "partial hash" while still keeping + * the possibility of adding more bytes to the input. + * + * - `br_xxx_state(const br_xxx_context *ctx, void *out)` + * + * Get a copy of the "current state" for the computation so far. For + * MD functions (MD5, SHA-1, SHA-2 family), this is the running state + * resulting from the processing of the last complete input block. + * Returned value is the current input length (in bytes). + * + * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)` + * + * Set the internal state to the provided values. The 'stb' and + * 'count' values shall match that which was obtained from + * `br_xxx_state()`. This restores the hash state only if the state + * values were at an appropriate block boundary. This does NOT set + * the `vtable` pointer in the context. + * + * Context structures can be discarded without any explicit deallocation. + * Hash function implementations are purely software and don't reserve + * any resources outside of the context structure itself. + * + * + * ## Object-Oriented API + * + * For each hash function that follows the procedural API described + * above, an object-oriented API is also provided. In that API, function + * pointers from the vtable (`br_xxx_vtable`) are used. The vtable + * incarnates object-oriented programming. An introduction on the OOP + * concept used here can be read on the BearSSL Web site:
    + *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) + * + * The vtable offers functions called `init()`, `update()`, `out()`, + * `set()` and `set_state()`, which are in fact the functions from + * the procedural API. That vtable also contains two informative fields: + * + * - `context_size` + * + * The size of the context structure (`br_xxx_context`), in bytes. + * This can be used by generic implementations to perform dynamic + * context allocation. + * + * - `desc` + * + * A "descriptor" field that encodes some information on the hash + * function: symbolic identifier, output size, state size, + * internal block size, details on the padding. + * + * Users of this object-oriented API (in particular generic HMAC + * implementations) may make the following assumptions: + * + * - Hash output size is no more than 64 bytes. + * - Hash internal state size is no more than 64 bytes. + * - Internal block size is a power of two, no less than 16 and no more + * than 256. + * + * + * ## Implemented Hash Functions + * + * Implemented hash functions are: + * + * | Function | Name | Output length | State length | + * | :-------- | :------ | :-----------: | :----------: | + * | MD5 | md5 | 16 | 16 | + * | SHA-1 | sha1 | 20 | 20 | + * | SHA-224 | sha224 | 28 | 32 | + * | SHA-256 | sha256 | 32 | 32 | + * | SHA-384 | sha384 | 48 | 64 | + * | SHA-512 | sha512 | 64 | 64 | + * | MD5+SHA-1 | md5sha1 | 36 | 36 | + * + * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the + * same input; in the implementation, the internal data buffer is + * shared, thus making it more memory-efficient than separate MD5 and + * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS + * 1.1.) + * + * + * ## Multi-Hasher + * + * An aggregate hasher is provided, that can compute several standard + * hash functions in parallel. It uses `br_multihash_context` and a + * procedural API. It is configured with the implementations (the vtables) + * that it should use; it will then compute all these hash functions in + * parallel, on the same input. It is meant to be used in cases when the + * hash of an object will be used, but the exact hash function is not + * known yet (typically, streamed processing on X.509 certificates). + * + * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 + * and SHA-512) are supported by the multi-hasher. + * + * + * ## GHASH + * + * GHASH is not a generic hash function; it is a _universal_ hash function, + * which, as the name does not say, means that it CANNOT be used in most + * places where a hash function is needed. GHASH is used within the GCM + * encryption mode, to provide the checked integrity functionality. + * + * A GHASH implementation is basically a function that uses the type defined + * in this file under the name `br_ghash`: + * + * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + * + * The `y` pointer refers to a 16-byte value which is used as input, and + * receives the output of the GHASH invocation. `h` is a 16-byte secret + * value (that serves as key). `data` and `len` define the input data. + * + * Three GHASH implementations are provided, all constant-time, based on + * the use of integer multiplications with appropriate masking to cancel + * carry propagation. + */ + +/** + * \brief Class type for hash function implementations. + * + * A `br_hash_class` instance references the methods implementing a hash + * function. Constant instances of this structure are defined for each + * implemented hash function. Such instances are also called "vtables". + * + * Vtables are used to support object-oriented programming, as + * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). + */ +typedef struct br_hash_class_ br_hash_class; +struct br_hash_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * computing this hash function. + */ + size_t context_size; + + /** + * \brief Descriptor word that contains information about the hash + * function. + * + * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` + * and `BR_HASHDESC_xxx_MASK` to access the specific value, as + * follows: + * + * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK + * + * The defined elements are: + * + * - `ID`: the symbolic identifier for the function, as defined + * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) + * (MD5 = 1, SHA-1 = 2,...). + * + * - `OUT`: hash output size, in bytes. + * + * - `STATE`: internal running state size, in bytes. + * + * - `LBLEN`: base-2 logarithm for the internal block size, as + * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 + * and SHA-256, since these functions use 64-byte blocks; for + * SHA-384 and SHA-512, this is 7, corresponding to their + * 128-byte blocks). + * + * The descriptor may contain a few other flags. + */ + uint32_t desc; + + /** + * \brief Initialisation method. + * + * This method takes as parameter a pointer to a context area, + * that it initialises. The first field of the context is set + * to this vtable; other elements are initialised for a new hash + * computation. + * + * \param ctx pointer to (the first field of) the context. + */ + void (*init)(const br_hash_class **ctx); + + /** + * \brief Data injection method. + * + * The `len` bytes starting at address `data` are injected into + * the running hash computation incarnated by the specified + * context. The context is updated accordingly. It is allowed + * to have `len == 0`, in which case `data` is ignored (and could + * be `NULL`), and nothing happens. + * on the input data. + * + * \param ctx pointer to (the first field of) the context. + * \param data pointer to the first data byte to inject. + * \param len number of bytes to inject. + */ + void (*update)(const br_hash_class **ctx, const void *data, size_t len); + + /** + * \brief Produce hash output. + * + * The hash output corresponding to all data bytes injected in the + * context since the last `init()` call is computed, and written + * in the buffer pointed to by `dst`. The hash output size depends + * on the implemented hash function (e.g. 16 bytes for MD5). + * The context is _not_ modified by this call, so further bytes + * may be afterwards injected to continue the current computation. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the hash output. + */ + void (*out)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Get running state. + * + * This method saves the current running state into the `dst` + * buffer. What constitutes the "running state" depends on the + * hash function; for Merkle-DamgÃ¥rd hash functions (like + * MD5 or SHA-1), this is the output obtained after processing + * each block. The number of bytes injected so far is returned. + * The context is not modified by this call. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the state. + * \return the injected total byte length. + */ + uint64_t (*state)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Set running state. + * + * This methods replaces the running state for the function. + * + * \param ctx pointer to (the first field of) the context. + * \param stb source buffer for the state. + * \param count injected total byte length. + */ + void (*set_state)(const br_hash_class **ctx, + const void *stb, uint64_t count); +}; + +#ifndef BR_DOXYGEN_IGNORE +#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) +#define BR_HASHDESC_ID_OFF 0 +#define BR_HASHDESC_ID_MASK 0xFF + +#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) +#define BR_HASHDESC_OUT_OFF 8 +#define BR_HASHDESC_OUT_MASK 0x7F + +#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) +#define BR_HASHDESC_STATE_OFF 15 +#define BR_HASHDESC_STATE_MASK 0xFF + +#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) +#define BR_HASHDESC_LBLEN_OFF 23 +#define BR_HASHDESC_LBLEN_MASK 0x0F + +#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) +#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) +#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) +#endif + +/* + * Specific hash functions. + * + * Rules for contexts: + * -- No interior pointer. + * -- No pointer to external dynamically allocated resources. + * -- First field is called 'vtable' and is a pointer to a + * const-qualified br_hash_class instance (pointer is set by init()). + * -- SHA-224 and SHA-256 contexts are identical. + * -- SHA-384 and SHA-512 contexts are identical. + * + * Thus, contexts can be moved and cloned to capture the hash function + * current state; and there is no need for any explicit "release" function. + */ + +/** + * \brief Symbolic identifier for MD5. + */ +#define br_md5_ID 1 + +/** + * \brief MD5 output size (in bytes). + */ +#define br_md5_SIZE 16 + +/** + * \brief Constant vtable for MD5. + */ +extern const br_hash_class br_md5_vtable; + +/** + * \brief MD5 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[4]; +#endif +} br_md5_context; + +/** + * \brief MD5 context initialisation. + * + * This function initialises or resets a context for a new MD5 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5_init(br_md5_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5_update(br_md5_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5 output. + * + * The MD5 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5_out(const br_md5_context *ctx, void *out); + +/** + * \brief Save MD5 running state. + * + * The running state for MD5 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5_state(const br_md5_context *ctx, void *out); + +/** + * \brief Restore MD5 running state. + * + * The running state for MD5 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-1. + */ +#define br_sha1_ID 2 + +/** + * \brief SHA-1 output size (in bytes). + */ +#define br_sha1_SIZE 20 + +/** + * \brief Constant vtable for SHA-1. + */ +extern const br_hash_class br_sha1_vtable; + +/** + * \brief SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[5]; +#endif +} br_sha1_context; + +/** + * \brief SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-1 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha1_init(br_sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-1 output. + * + * The SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha1_out(const br_sha1_context *ctx, void *out); + +/** + * \brief Save SHA-1 running state. + * + * The running state for SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); + +/** + * \brief Restore SHA-1 running state. + * + * The running state for SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-224. + */ +#define br_sha224_ID 3 + +/** + * \brief SHA-224 output size (in bytes). + */ +#define br_sha224_SIZE 28 + +/** + * \brief Constant vtable for SHA-224. + */ +extern const br_hash_class br_sha224_vtable; + +/** + * \brief SHA-224 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[8]; +#endif +} br_sha224_context; + +/** + * \brief SHA-224 context initialisation. + * + * This function initialises or resets a context for a new SHA-224 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha224_init(br_sha224_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-224 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-224 output. + * + * The SHA-224 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha224_out(const br_sha224_context *ctx, void *out); + +/** + * \brief Save SHA-224 running state. + * + * The running state for SHA-224 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); + +/** + * \brief Restore SHA-224 running state. + * + * The running state for SHA-224 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha224_set_state(br_sha224_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-256. + */ +#define br_sha256_ID 4 + +/** + * \brief SHA-256 output size (in bytes). + */ +#define br_sha256_SIZE 32 + +/** + * \brief Constant vtable for SHA-256. + */ +extern const br_hash_class br_sha256_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-256 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha256_context; +#else +typedef br_sha224_context br_sha256_context; +#endif + +/** + * \brief SHA-256 context initialisation. + * + * This function initialises or resets a context for a new SHA-256 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha256_init(br_sha256_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-256 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); +#else +#define br_sha256_update br_sha224_update +#endif + +/** + * \brief Compute SHA-256 output. + * + * The SHA-256 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha256_out(const br_sha256_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-256 running state. + * + * The running state for SHA-256 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); +#else +#define br_sha256_state br_sha224_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-256 running state. + * + * The running state for SHA-256 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha256_set_state(br_sha256_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha256_set_state br_sha224_set_state +#endif + +/** + * \brief Symbolic identifier for SHA-384. + */ +#define br_sha384_ID 5 + +/** + * \brief SHA-384 output size (in bytes). + */ +#define br_sha384_SIZE 48 + +/** + * \brief Constant vtable for SHA-384. + */ +extern const br_hash_class br_sha384_vtable; + +/** + * \brief SHA-384 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint64_t val[8]; +#endif +} br_sha384_context; + +/** + * \brief SHA-384 context initialisation. + * + * This function initialises or resets a context for a new SHA-384 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha384_init(br_sha384_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-384 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-384 output. + * + * The SHA-384 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha384_out(const br_sha384_context *ctx, void *out); + +/** + * \brief Save SHA-384 running state. + * + * The running state for SHA-384 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); + +/** + * \brief Restore SHA-384 running state. + * + * The running state for SHA-384 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha384_set_state(br_sha384_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-512. + */ +#define br_sha512_ID 6 + +/** + * \brief SHA-512 output size (in bytes). + */ +#define br_sha512_SIZE 64 + +/** + * \brief Constant vtable for SHA-512. + */ +extern const br_hash_class br_sha512_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-512 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha512_context; +#else +typedef br_sha384_context br_sha512_context; +#endif + +/** + * \brief SHA-512 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha512_init(br_sha512_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-512 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); +#else +#define br_sha512_update br_sha384_update +#endif + +/** + * \brief Compute SHA-512 output. + * + * The SHA-512 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha512_out(const br_sha512_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-512 running state. + * + * The running state for SHA-512 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); +#else +#define br_sha512_state br_sha384_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-512 running state. + * + * The running state for SHA-512 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha512_set_state(br_sha512_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha512_set_state br_sha384_set_state +#endif + +/* + * "md5sha1" is a special hash function that computes both MD5 and SHA-1 + * on the same input, and produces a 36-byte output (MD5 and SHA-1 + * concatenation, in that order). State size is also 36 bytes. + */ + +/** + * \brief Symbolic identifier for MD5+SHA-1. + * + * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the + * same input. It is not one of the functions identified in TLS, so + * we give it a symbolic identifier of value 0. + */ +#define br_md5sha1_ID 0 + +/** + * \brief MD5+SHA-1 output size (in bytes). + */ +#define br_md5sha1_SIZE 36 + +/** + * \brief Constant vtable for MD5+SHA-1. + */ +extern const br_hash_class br_md5sha1_vtable; + +/** + * \brief MD5+SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val_md5[4]; + uint32_t val_sha1[5]; +#endif +} br_md5sha1_context; + +/** + * \brief MD5+SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5sha1_init(br_md5sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5+SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5+SHA-1 output. + * + * The MD5+SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Save MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Restore MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5sha1_set_state(br_md5sha1_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Aggregate context for configurable hash function support. + * + * The `br_hash_compat_context` type is a type which is large enough to + * serve as context for all standard hash functions defined above. + */ +typedef union { + const br_hash_class *vtable; + br_md5_context md5; + br_sha1_context sha1; + br_sha224_context sha224; + br_sha256_context sha256; + br_sha384_context sha384; + br_sha512_context sha512; + br_md5sha1_context md5sha1; +} br_hash_compat_context; + +/* + * The multi-hasher is a construct that handles hashing of the same input + * data with several hash functions, with a single shared input buffer. + * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 + * simultaneously, though which functions are activated depends on + * the set implementation pointers. + */ + +/** + * \brief Multi-hasher context structure. + * + * The multi-hasher runs up to six hash functions in the standard TLS list + * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over + * the same input. + * + * The multi-hasher does _not_ follow the OOP structure with a vtable. + * Instead, it is configured with the vtables of the hash functions it + * should run. Structure fields are not supposed to be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint32_t val_32[25]; + uint64_t val_64[16]; + const br_hash_class *impl[6]; +#endif +} br_multihash_context; + +/** + * \brief Clear a multi-hasher context. + * + * This should always be called once on a given context, _before_ setting + * the implementation pointers. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_zero(br_multihash_context *ctx); + +/** + * \brief Set a hash function implementation. + * + * Implementations shall be set _after_ clearing the context (with + * `br_multihash_zero()`) but _before_ initialising the computation + * (with `br_multihash_init()`). The hash function implementation + * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, + * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove + * an implementation from the multi-hasher. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \param impl the hash function vtable, or `NULL`. + */ +static inline void +br_multihash_setimpl(br_multihash_context *ctx, + int id, const br_hash_class *impl) +{ + /* + * This code relies on hash functions ID being values 1 to 6, + * in the MD5 to SHA-512 order. + */ + ctx->impl[id - 1] = impl; +} + +/** + * \brief Get a hash function implementation. + * + * This function returns the currently configured vtable for a given + * hash function (by symbolic ID). If no such function was configured in + * the provided multi-hasher context, then this function returns `NULL`. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \return the hash function vtable, or `NULL`. + */ +static inline const br_hash_class * +br_multihash_getimpl(const br_multihash_context *ctx, int id) +{ + return ctx->impl[id - 1]; +} + +/** + * \brief Reset a multi-hasher context. + * + * This function prepares the context for a new hashing computation, + * for all implementations configured at that point. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_init(br_multihash_context *ctx); + +/** + * \brief Inject some data bytes in a running multi-hashing computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_multihash_update(br_multihash_context *ctx, + const void *data, size_t len); + +/** + * \brief Compute a hash output from a multi-hasher. + * + * The hash output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `dst`. The hash + * function to use is identified by `id` and must be one of the standard + * hash functions. If that hash function was indeed configured in the + * multi-hasher context, the corresponding hash value is written in + * `dst` and its length (in bytes) is returned. If the hash function + * was _not_ configured, then nothing is written in `dst` and 0 is + * returned. + * + * The context itself is not modified, so extra bytes may be injected + * afterwards to continue the hash computations. + * + * \param ctx pointer to the context structure. + * \param id the hash function symbolic identifier. + * \param dst destination buffer for the hash output. + * \return the hash output length (in bytes), or 0. + */ +size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); + +/** + * \brief Type for a GHASH implementation. + * + * GHASH is a sort of keyed hash meant to be used to implement GCM in + * combination with a block cipher (with 16-byte blocks). + * + * The `y` array has length 16 bytes and is used for input and output; in + * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte + * value that serves as key (it is derived from the encryption key in GCM, + * using the block cipher). The data length (`len`) is expressed in bytes. + * The `y` array is updated. + * + * If the data length is not a multiple of 16, then the data is implicitly + * padded with zeros up to the next multiple of 16. Thus, when using GHASH + * in GCM, this method may be called twice, for the associated data and + * for the ciphertext, respectively; the zero-padding implements exactly + * the GCM rules. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (mixed 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (strict 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, + * but it is expected to be faster on architectures for which the + * 32-bit multiplication opcode does not yield the upper 32 bits of the + * product. It is constant-time (if multiplications are constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (64-bit). + * + * This implementation uses multiplications of 64-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). It is substantially faster than `br_ghash_ctmul()` + * and `br_ghash_ctmul32()` on most 64-bit architectures. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using the `pclmulqdq` opcode (part of the + * AES-NI instructions). + * + * This implementation is available only on x86 platforms where the + * compiler supports the relevant intrinsic functions. Even if the + * compiler supports these functions, the local CPU might not support + * the `pclmulqdq` opcode, meaning that a call will fail with an + * illegal instruction exception. To safely obtain a pointer to this + * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pclmul` GHASH implementation, if available. + * + * If the `pclmul` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pclmul()` function. Otherwise, it will return `0`. + * + * \return the `pclmul` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pclmul_get(void); + +/** + * \brief GHASH implementation using the POWER8 opcodes. + * + * This implementation is available only on POWER8 platforms (and later). + * To safely obtain a pointer to this function when supported (or 0 + * otherwise), use `br_ghash_pwr8_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pwr8` GHASH implementation, if available. + * + * If the `pwr8` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pwr8()` function. Otherwise, it will return `0`. + * + * \return the `pwr8` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pwr8_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_hmac.h b/template/sysroot/include/bearssl_hmac.h new file mode 100644 index 0000000..4dc01ca --- /dev/null +++ b/template/sysroot/include/bearssl_hmac.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HMAC_H__ +#define BR_BEARSSL_HMAC_H__ + +#include +#include + +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hmac.h + * + * # HMAC + * + * HMAC is initialized with a key and an underlying hash function; it + * then fills a "key context". That context contains the processed + * key. + * + * With the key context, a HMAC context can be initialized to process + * the input bytes and obtain the MAC output. The key context is not + * modified during that process, and can be reused. + * + * IMPORTANT: HMAC shall be used only with functions that have the + * following properties: + * + * - hash output size does not exceed 64 bytes; + * - hash internal state size does not exceed 64 bytes; + * - internal block length is a power of 2 between 16 and 256 bytes. + */ + +/** + * \brief HMAC key context. + * + * The HMAC key context is initialised with a hash function implementation + * and a secret key. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_hash_class *dig_vtable; + unsigned char ksi[64], kso[64]; +#endif +} br_hmac_key_context; + +/** + * \brief HMAC key context initialisation. + * + * Initialise the key context with the provided key, using the hash function + * identified by `digest_vtable`. This supports arbitrary key lengths. + * + * \param kc HMAC key context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param key pointer to the HMAC secret key. + * \param key_len HMAC secret key length (in bytes). + */ +void br_hmac_key_init(br_hmac_key_context *kc, + const br_hash_class *digest_vtable, const void *key, size_t key_len); + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC key context. + * + * \param kc HMAC key context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_key_get_digest( + const br_hmac_key_context *kc) +{ + return kc->dig_vtable; +} + +/** + * \brief HMAC computation context. + * + * The HMAC computation context maintains the state for a single HMAC + * computation. It is modified as input bytes are injected. The context + * is caller-allocated and has no release function since it does not + * dynamically allocate external resources. Its contents are opaque. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_hash_compat_context dig; + unsigned char kso[64]; + size_t out_len; +#endif +} br_hmac_context; + +/** + * \brief HMAC computation initialisation. + * + * Initialise a HMAC context with a key context. The key context is + * unmodified. Relevant data from the key context is immediately copied; + * the key context can thus be independently reused, modified or released + * without impacting this HMAC computation. + * + * An explicit output length can be specified; the actual output length + * will be the minimum of that value and the natural HMAC output length. + * If `out_len` is 0, then the natural HMAC output length is selected. The + * "natural output length" is the output length of the underlying hash + * function. + * + * \param ctx HMAC context to initialise. + * \param kc HMAC key context (already initialised with the key). + * \param out_len HMAC output length (0 to select "natural length"). + */ +void br_hmac_init(br_hmac_context *ctx, + const br_hmac_key_context *kc, size_t out_len); + +/** + * \brief Get the HMAC output size. + * + * The HMAC output size is the number of bytes that will actually be + * produced with `br_hmac_out()` with the provided context. This function + * MUST NOT be called on a non-initialised HMAC computation context. + * The returned value is the minimum of the HMAC natural length (output + * size of the underlying hash function) and the `out_len` parameter which + * was used with the last `br_hmac_init()` call on that context (if the + * initialisation `out_len` parameter was 0, then this function will + * return the HMAC natural length). + * + * \param ctx the (already initialised) HMAC computation context. + * \return the HMAC actual output size. + */ +static inline size_t +br_hmac_size(br_hmac_context *ctx) +{ + return ctx->out_len; +} + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC context. + * + * \param hc HMAC context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_get_digest( + const br_hmac_context *hc) +{ + return hc->dig.vtable; +} + +/** + * \brief Inject some bytes in HMAC. + * + * The provided `len` bytes are injected as extra input in the HMAC + * computation incarnated by the `ctx` HMAC context. It is acceptable + * that `len` is zero, in which case `data` is ignored (and may be + * `NULL`) and this function does nothing. + */ +void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); + +/** + * \brief Compute the HMAC output. + * + * The destination buffer MUST be large enough to accommodate the result; + * its length is at most the "natural length" of HMAC (i.e. the output + * length of the underlying hash function). The context is NOT modified; + * further bytes may be processed. Thus, "partial HMAC" values can be + * efficiently obtained. + * + * Returned value is the output length (in bytes). + * + * \param ctx HMAC computation context. + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_out(const br_hmac_context *ctx, void *out); + +/** + * \brief Constant-time HMAC computation. + * + * This function compute the HMAC output in constant time. Some extra + * input bytes are processed, then the output is computed. The extra + * input consists in the `len` bytes pointed to by `data`. The `len` + * parameter must lie between `min_len` and `max_len` (inclusive); + * `max_len` bytes are actually read from `data`. Computing time (and + * memory access pattern) will not depend upon the data byte contents or + * the value of `len`. + * + * The output is written in the `out` buffer, that MUST be large enough + * to receive it. + * + * The difference `max_len - min_len` MUST be less than 230 + * (i.e. about one gigabyte). + * + * This function computes the output properly only if the underlying + * hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 or SHA-512). + * + * The provided context is NOT modified. + * + * \param ctx the (already initialised) HMAC computation context. + * \param data the extra input bytes. + * \param len the extra input length (in bytes). + * \param min_len minimum extra input length (in bytes). + * \param max_len maximum extra input length (in bytes). + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_outCT(const br_hmac_context *ctx, + const void *data, size_t len, size_t min_len, size_t max_len, + void *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_kdf.h b/template/sysroot/include/bearssl_kdf.h new file mode 100644 index 0000000..955b843 --- /dev/null +++ b/template/sysroot/include/bearssl_kdf.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_KDF_H__ +#define BR_BEARSSL_KDF_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_kdf.h + * + * # Key Derivation Functions + * + * KDF are functions that takes a variable length input, and provide a + * variable length output, meant to be used to derive subkeys from a + * master key. + * + * ## HKDF + * + * HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869). + * It is based on HMAC, itself using an underlying hash function. Any + * hash function can be used, as long as it is compatible with the rules + * for the HMAC implementation (i.e. output size is 64 bytes or less, hash + * internal state size is 64 bytes or less, and the internal block length is + * a power of 2 between 16 and 256 bytes). HKDF has two phases: + * + * - HKDF-Extract: the input data in ingested, along with a "salt" value. + * + * - HKDF-Expand: the output is produced, from the result of processing + * the input and salt, and using an extra non-secret parameter called + * "info". + * + * The "salt" and "info" strings are non-secret and can be empty. Their role + * is normally to bind the input and output, respectively, to conventional + * identifiers that qualifu them within the used protocol or application. + * + * The implementation defined in this file uses the following functions: + * + * - `br_hkdf_init()`: initialize an HKDF context, with a hash function, + * and the salt. This starts the HKDF-Extract process. + * + * - `br_hkdf_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_hkdf_flip()`: end the HKDF-Extract process, and start the + * HKDF-Expand process. + * + * - `br_hkdf_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + * For correct HKDF processing, the same "info" string must be + * provided for each call. + * + * Note that the HKDF total output size (the number of bytes that + * HKDF-Expand is willing to produce) is limited: if the hash output size + * is _n_ bytes, then the maximum output size is _255*n_. + * + * ## SHAKE + * + * SHAKE is defined in + * [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final) + * under two versions: SHAKE128 and SHAKE256, offering an alleged + * "security level" of 128 and 256 bits, respectively (SHAKE128 is + * about 20 to 25% faster than SHAKE256). SHAKE internally relies on + * the Keccak family of sponge functions, not on any externally provided + * hash function. Contrary to HKDF, SHAKE does not have a concept of + * either a "salt" or an "info" string. The API consists in four + * functions: + * + * - `br_shake_init()`: initialize a SHAKE context for a given + * security level. + * + * - `br_shake_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_shake_flip()`: end the data injection process, and start the + * data production process. + * + * - `br_shake_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + */ + +/** + * \brief HKDF context. + * + * The HKDF context is initialized with a hash function implementation + * and a salt value. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + union { + br_hmac_context hmac_ctx; + br_hmac_key_context prk_ctx; + } u; + unsigned char buf[64]; + size_t ptr; + size_t dig_len; + unsigned chunk_num; +#endif +} br_hkdf_context; + +/** + * \brief HKDF context initialization. + * + * The underlying hash function and salt value are provided. Arbitrary + * salt lengths can be used. + * + * HKDF makes a difference between a salt of length zero, and an + * absent salt (the latter being equivalent to a salt consisting of + * bytes of value zero, of the same length as the hash function output). + * If `salt_len` is zero, then this function assumes that the salt is + * present but of length zero. To specify an _absent_ salt, use + * `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored). + * + * \param hc HKDF context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param salt HKDF-Extract salt. + * \param salt_len HKDF-Extract salt length (in bytes). + */ +void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, + const void *salt, size_t salt_len); + +/** + * \brief The special "absent salt" value for HKDF. + */ +#define BR_HKDF_NO_SALT (&br_hkdf_no_salt) + +#ifndef BR_DOXYGEN_IGNORE +extern const unsigned char br_hkdf_no_salt; +#endif + +/** + * \brief HKDF input injection (HKDF-Extract). + * + * This function injects some more input bytes ("key material") into + * HKDF. This function may be called several times, after `br_hkdf_init()` + * but before `br_hkdf_flip()`. + * + * \param hc HKDF context. + * \param ikm extra input bytes. + * \param ikm_len number of extra input bytes. + */ +void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len); + +/** + * \brief HKDF switch to the HKDF-Expand phase. + * + * This call terminates the HKDF-Extract process (input injection), and + * starts the HKDF-Expand process (output production). + * + * \param hc HKDF context. + */ +void br_hkdf_flip(br_hkdf_context *hc); + +/** + * \brief HKDF output production (HKDF-Expand). + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_hkdf_flip()`. + * + * Returned value is the number of actually produced bytes. The total + * output length is limited to 255 times the output length of the + * underlying hash function. + * + * \param hc HKDF context. + * \param info application specific information string. + * \param info_len application specific information string length (in bytes). + * \param out destination buffer for the HKDF output. + * \param out_len the length of the requested output (in bytes). + * \return the produced output length (in bytes). + */ +size_t br_hkdf_produce(br_hkdf_context *hc, + const void *info, size_t info_len, void *out, size_t out_len); + +/** + * \brief SHAKE context. + * + * The HKDF context is initialized with a "security level". The internal + * notion is called "capacity"; the capacity is twice the security level + * (for instance, SHAKE128 has capacity 256). + * + * The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char dbuf[200]; + size_t dptr; + size_t rate; + uint64_t A[25]; +#endif +} br_shake_context; + +/** + * \brief SHAKE context initialization. + * + * The context is initialized for the provided "security level". + * Internally, this sets the "capacity" to twice the security level; + * thus, for SHAKE128, the `security_level` parameter should be 128, + * which corresponds to a 256-bit capacity. + * + * Allowed security levels are all multiples of 32, from 32 to 768, + * inclusive. Larger security levels imply lower performance; levels + * beyond 256 bits don't make much sense. Standard levels are 128 + * and 256 bits (for SHAKE128 and SHAKE256, respectively). + * + * \param sc SHAKE context to initialise. + * \param security_level security level (in bits). + */ +void br_shake_init(br_shake_context *sc, int security_level); + +/** + * \brief SHAKE input injection. + * + * This function injects some more input bytes ("key material") into + * SHAKE. This function may be called several times, after `br_shake_init()` + * but before `br_shake_flip()`. + * + * \param sc SHAKE context. + * \param data extra input bytes. + * \param len number of extra input bytes. + */ +void br_shake_inject(br_shake_context *sc, const void *data, size_t len); + +/** + * \brief SHAKE switch to production phase. + * + * This call terminates the input injection process, and starts the + * output production process. + * + * \param sc SHAKE context. + */ +void br_shake_flip(br_shake_context *hc); + +/** + * \brief SHAKE output production. + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_shake_flip()`. + * + * There is no practical limit to the number of bytes that may be produced. + * + * \param sc SHAKE context. + * \param out destination buffer for the SHAKE output. + * \param len the length of the requested output (in bytes). + */ +void br_shake_produce(br_shake_context *sc, void *out, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_pem.h b/template/sysroot/include/bearssl_pem.h new file mode 100644 index 0000000..8dba582 --- /dev/null +++ b/template/sysroot/include/bearssl_pem.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PEM_H__ +#define BR_BEARSSL_PEM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_pem.h + * + * # PEM Support + * + * PEM is a traditional encoding layer use to store binary objects (in + * particular X.509 certificates, and private keys) in text files. While + * the acronym comes from an old, defunct standard ("Privacy Enhanced + * Mail"), the format has been reused, with some variations, by many + * systems, and is a _de facto_ standard, even though it is not, actually, + * specified in all clarity anywhere. + * + * ## Format Details + * + * BearSSL contains a generic, streamed PEM decoder, which handles the + * following format: + * + * - The input source (a sequence of bytes) is assumed to be the + * encoding of a text file in an ASCII-compatible charset. This + * includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each + * line ends on a newline character (U+000A LINE FEED). The + * U+000D CARRIAGE RETURN characters are ignored, so the code + * accepts both Windows-style and Unix-style line endings. + * + * - Each object begins with a banner that occurs at the start of + * a line; the first banner characters are "`-----BEGIN `" (five + * dashes, the word "BEGIN", and a space). The banner matching is + * not case-sensitive. + * + * - The _object name_ consists in the characters that follow the + * banner start sequence, up to the end of the line, but without + * trailing dashes (in "normal" PEM, there are five trailing + * dashes, but this implementation is not picky about these dashes). + * The BearSSL decoder normalises the name characters to uppercase + * (for ASCII letters only) and accepts names up to 127 characters. + * + * - The object ends with a banner that again occurs at the start of + * a line, and starts with "`-----END `" (again case-insensitive). + * + * - Between that start and end banner, only Base64 data shall occur. + * Base64 converts each sequence of three bytes into four + * characters; the four characters are ASCII letters, digits, "`+`" + * or "`-`" signs, and one or two "`=`" signs may occur in the last + * quartet. Whitespace is ignored (whitespace is any ASCII character + * of code 32 or less, so control characters are whitespace) and + * lines may have arbitrary length; the only restriction is that the + * four characters of a quartet must appear on the same line (no + * line break inside a quartet). + * + * - A single file may contain more than one PEM object. Bytes that + * occur between objects are ignored. + * + * + * ## PEM Decoder API + * + * The PEM decoder offers a state-machine API. The caller allocates a + * decoder context, then injects source bytes. Source bytes are pushed + * with `br_pem_decoder_push()`. The decoder stops accepting bytes when + * it reaches an "event", which is either the start of an object, the + * end of an object, or a decoding error within an object. + * + * The `br_pem_decoder_event()` function is used to obtain the current + * event; it also clears it, thus allowing the decoder to accept more + * bytes. When a object start event is raised, the decoder context + * offers the found object name (normalised to ASCII uppercase). + * + * When an object is reached, the caller must set an appropriate callback + * function, which will receive (by chunks) the decoded object data. + * + * Since the decoder context makes no dynamic allocation, it requires + * no explicit deallocation. + */ + +/** + * \brief PEM decoder context. + * + * Contents are opaque (they should not be accessed directly). + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + const unsigned char *hbuf; + size_t hlen; + + void (*dest)(void *dest_ctx, const void *src, size_t len); + void *dest_ctx; + + unsigned char event; + char name[128]; + unsigned char buf[255]; + size_t ptr; +#endif +} br_pem_decoder_context; + +/** + * \brief Initialise a PEM decoder structure. + * + * \param ctx decoder context to initialise. + */ +void br_pem_decoder_init(br_pem_decoder_context *ctx); + +/** + * \brief Push some bytes into the decoder. + * + * Returned value is the number of bytes actually consumed; this may be + * less than the number of provided bytes if an event is raised. When an + * event is raised, it must be read (with `br_pem_decoder_event()`); + * until the event is read, this function will return 0. + * + * \param ctx decoder context. + * \param data new data bytes. + * \param len number of new data bytes. + * \return the number of bytes actually received (may be less than `len`). + */ +size_t br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Set the receiver for decoded data. + * + * When an object is entered, the provided function (with opaque context + * pointer) will be called repeatedly with successive chunks of decoded + * data for that object. If `dest` is set to 0, then decoded data is + * simply ignored. The receiver can be set at any time, but, in practice, + * it should be called immediately after receiving a "start of object" + * event. + * + * \param ctx decoder context. + * \param dest callback for receiving decoded data. + * \param dest_ctx opaque context pointer for the `dest` callback. + */ +static inline void +br_pem_decoder_setdest(br_pem_decoder_context *ctx, + void (*dest)(void *dest_ctx, const void *src, size_t len), + void *dest_ctx) +{ + ctx->dest = dest; + ctx->dest_ctx = dest_ctx; +} + +/** + * \brief Get the last event. + * + * If an event was raised, then this function returns the event value, and + * also clears it, thereby allowing the decoder to proceed. If no event + * was raised since the last call to `br_pem_decoder_event()`, then this + * function returns 0. + * + * \param ctx decoder context. + * \return the raised event, or 0. + */ +int br_pem_decoder_event(br_pem_decoder_context *ctx); + +/** + * \brief Event: start of object. + * + * This event is raised when the start of a new object has been detected. + * The object name (normalised to uppercase) can be accessed with + * `br_pem_decoder_name()`. + */ +#define BR_PEM_BEGIN_OBJ 1 + +/** + * \brief Event: end of object. + * + * This event is raised when the end of the current object is reached + * (normally, i.e. with no decoding error). + */ +#define BR_PEM_END_OBJ 2 + +/** + * \brief Event: decoding error. + * + * This event is raised when decoding fails within an object. + * This formally closes the current object and brings the decoder back + * to the "out of any object" state. The offending line in the source + * is consumed. + */ +#define BR_PEM_ERROR 3 + +/** + * \brief Get the name of the encountered object. + * + * The encountered object name is defined only when the "start of object" + * event is raised. That name is normalised to uppercase (for ASCII letters + * only) and does not include trailing dashes. + * + * \param ctx decoder context. + * \return the current object name. + */ +static inline const char * +br_pem_decoder_name(br_pem_decoder_context *ctx) +{ + return ctx->name; +} + +/** + * \brief Encode an object in PEM. + * + * This function encodes the provided binary object (`data`, of length `len` + * bytes) into PEM. The `banner` text will be included in the header and + * footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header). + * + * The length (in characters) of the PEM output is returned; that length + * does NOT include the terminating zero, that this function nevertheless + * adds. If using the returned value for allocation purposes, the allocated + * buffer size MUST be at least one byte larger than the returned size. + * + * If `dest` is `NULL`, then the encoding does not happen; however, the + * length of the encoded object is still computed and returned. + * + * The `data` pointer may be `NULL` only if `len` is zero (when encoding + * an object of length zero, which is not very useful), or when `dest` + * is `NULL` (in that case, source data bytes are ignored). + * + * Some `flags` can be specified to alter the encoding behaviour: + * + * - If `BR_PEM_LINE64` is set, then line-breaking will occur after + * every 64 characters of output, instead of the default of 76. + * + * - If `BR_PEM_CRLF` is set, then end-of-line sequence will use + * CR+LF instead of a single LF. + * + * The `data` and `dest` buffers may overlap, in which case the source + * binary data is destroyed in the process. Note that the PEM-encoded output + * is always larger than the source binary. + * + * \param dest the destination buffer (or `NULL`). + * \param data the source buffer (can be `NULL` in some cases). + * \param len the source length (in bytes). + * \param banner the PEM banner expression. + * \param flags the behavioural flags. + * \return the PEM object length (in characters), EXCLUDING the final zero. + */ +size_t br_pem_encode(void *dest, const void *data, size_t len, + const char *banner, unsigned flags); + +/** + * \brief PEM encoding flag: split lines at 64 characters. + */ +#define BR_PEM_LINE64 0x0001 + +/** + * \brief PEM encoding flag: use CR+LF line endings. + */ +#define BR_PEM_CRLF 0x0002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_prf.h b/template/sysroot/include/bearssl_prf.h new file mode 100644 index 0000000..fdf608c --- /dev/null +++ b/template/sysroot/include/bearssl_prf.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PRF_H__ +#define BR_BEARSSL_PRF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_prf.h + * + * # The TLS PRF + * + * The "PRF" is the pseudorandom function used internally during the + * SSL/TLS handshake, notably to expand negotiated shared secrets into + * the symmetric encryption keys that will be used to process the + * application data. + * + * TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This + * is implemented by the `br_tls10_prf()` function. + * + * TLS 1.2 redefines the PRF, using an explicit hash function. The + * `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that + * PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites + * rely on the SHA-256 based PRF, but some use SHA-384. + * + * The PRF always uses as input three parameters: a "secret" (some + * bytes), a "label" (ASCII string), and a "seed" (again some bytes). An + * arbitrary output length can be produced. The "seed" is provided as an + * arbitrary number of binary chunks, that gets internally concatenated. + */ + +/** + * \brief Type for a seed chunk. + * + * Each chunk may have an arbitrary length, and may be empty (no byte at + * all). If the chunk length is zero, then the pointer to the chunk data + * may be `NULL`. + */ +typedef struct { + /** + * \brief Pointer to the chunk data. + */ + const void *data; + + /** + * \brief Chunk length (in bytes). + */ + size_t len; +} br_tls_prf_seed_chunk; + +/** + * \brief PRF implementation for TLS 1.0 and 1.1. + * + * This PRF is the one specified by TLS 1.0 and 1.1. It internally uses + * MD5 and SHA-1. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls10_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-256. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-256. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha256_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-384. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-384. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha384_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * brief A convenient type name for a PRF implementation. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +typedef void (*br_tls_prf_impl)(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_rand.h b/template/sysroot/include/bearssl_rand.h new file mode 100644 index 0000000..0a9f544 --- /dev/null +++ b/template/sysroot/include/bearssl_rand.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RAND_H__ +#define BR_BEARSSL_RAND_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rand.h + * + * # Pseudo-Random Generators + * + * A PRNG is a state-based engine that outputs pseudo-random bytes on + * demand. It is initialized with an initial seed, and additional seed + * bytes can be added afterwards. Bytes produced depend on the seeds and + * also on the exact sequence of calls (including sizes requested for + * each call). + * + * + * ## Procedural and OOP API + * + * For the PRNG of name "`xxx`", two API are provided. The _procedural_ + * API defined a context structure `br_xxx_context` and three functions: + * + * - `br_xxx_init()` + * + * Initialise the context with an initial seed. + * + * - `br_xxx_generate()` + * + * Produce some pseudo-random bytes. + * + * - `br_xxx_update()` + * + * Inject some additional seed. + * + * The initialisation function sets the first context field (`vtable`) + * to a pointer to the vtable that supports the OOP API. The OOP API + * provides access to the same functions through function pointers, + * named `init()`, `generate()` and `update()`. + * + * Note that the context initialisation method may accept additional + * parameters, provided as a 'const void *' pointer at API level. These + * additional parameters depend on the implemented PRNG. + * + * + * ## HMAC_DRBG + * + * HMAC_DRBG is defined in [NIST SP 800-90A Revision + * 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf). + * It uses HMAC repeatedly, over some configurable underlying hash + * function. In BearSSL, it is implemented under the "`hmac_drbg`" name. + * The "extra parameters" pointer for context initialisation should be + * set to a pointer to the vtable for the underlying hash function (e.g. + * pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256). + * + * According to the NIST standard, each request shall produce up to + * 219 bits (i.e. 64 kB of data); moreover, the context shall + * be reseeded at least once every 248 requests. This + * implementation does not maintain the reseed counter (the threshold is + * too high to be reached in practice) and does not object to producing + * more than 64 kB in a single request; thus, the code cannot fail, + * which corresponds to the fact that the API has no room for error + * codes. However, this implies that requesting more than 64 kB in one + * `generate()` request, or making more than 248 requests + * without reseeding, is formally out of NIST specification. There is + * no currently known security penalty for exceeding the NIST limits, + * and, in any case, HMAC_DRBG usage in implementing SSL/TLS always + * stays much below these thresholds. + * + * + * ## AESCTR_DRBG + * + * AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is + * meant to be used only in situations where you are desperate for + * speed, and have an hardware-optimized AES/CTR implementation. Whether + * this will yield perceptible improvements depends on what you use the + * pseudorandom bytes for, and how many you want; for instance, RSA key + * pair generation uses a substantial amount of randomness, and using + * AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key + * generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz). + * + * Internally, it uses CTR mode with successive counter values, starting + * at zero (counter value expressed over 128 bits, big-endian convention). + * The counter is not allowed to reach 32768; thus, every 32768*16 bytes + * at most, the `update()` function is run (on an empty seed, if none is + * provided). The `update()` function computes the new AES-128 key by + * applying a custom hash function to the concatenation of a state-dependent + * word (encryption of an all-one block with the current key) and the new + * seed. The custom hash function uses Hirose's construction over AES-256; + * see the comments in `aesctr_drbg.c` for details. + * + * This DRBG does not follow an existing standard, and thus should be + * considered as inadequate for production use until it has been properly + * analysed. + */ + +/** + * \brief Class type for PRNG implementations. + * + * A `br_prng_class` instance references the methods implementing a PRNG. + * Constant instances of this structure are defined for each implemented + * PRNG. Such instances are also called "vtables". + */ +typedef struct br_prng_class_ br_prng_class; +struct br_prng_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * running this PRNG. + */ + size_t context_size; + + /** + * \brief Initialisation method. + * + * The context to initialise is provided as a pointer to its + * first field (the vtable pointer); this function sets that + * first field to a pointer to the vtable. + * + * The extra parameters depend on the implementation; each + * implementation defines what kind of extra parameters it + * expects (if any). + * + * Requirements on the initial seed depend on the implemented + * PRNG. + * + * \param ctx PRNG context to initialise. + * \param params extra parameters for the PRNG. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ + void (*init)(const br_prng_class **ctx, const void *params, + const void *seed, size_t seed_len); + + /** + * \brief Random bytes generation. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx PRNG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ + void (*generate)(const br_prng_class **ctx, void *out, size_t len); + + /** + * \brief Inject additional seed bytes. + * + * The provided seed bytes are added into the PRNG internal + * entropy pool. + * + * \param ctx PRNG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ + void (*update)(const br_prng_class **ctx, + const void *seed, size_t seed_len); +}; + +/** + * \brief Context for HMAC_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char K[64]; + unsigned char V[64]; + const br_hash_class *digest_class; +#endif +} br_hmac_drbg_context; + +/** + * \brief Statically allocated, constant vtable for HMAC_DRBG. + */ +extern const br_prng_class br_hmac_drbg_vtable; + +/** + * \brief HMAC_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The `seed` value is what is called, in NIST terminology, the + * concatenation of the "seed", "nonce" and "personalization string", in + * that order. + * + * The `digest_class` parameter defines the underlying hash function. + * Formally, the NIST standard specifies that the hash function shall + * be only SHA-1 or one of the SHA-2 functions. This implementation also + * works with any other implemented hash function (such as MD5), but + * this is non-standard and therefore not recommended. + * + * \param ctx HMAC_DRBG context to initialise. + * \param digest_class vtable for the underlying hash function. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ +void br_hmac_drbg_init(br_hmac_drbg_context *ctx, + const br_hash_class *digest_class, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with HMAC_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. Formally, requesting + * more than 65536 bytes in one request falls out of specification + * limits (but it won't fail). + * + * \param ctx HMAC_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); + +/** + * \brief Inject additional seed bytes in HMAC_DRBG. + * + * The provided seed bytes are added into the HMAC_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx HMAC_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_hmac_drbg_update(br_hmac_drbg_context *ctx, + const void *seed, size_t seed_len); + +/** + * \brief Get the hash function implementation used by a given instance of + * HMAC_DRBG. + * + * This calls MUST NOT be performed on a context which was not + * previously initialised. + * + * \param ctx HMAC_DRBG context. + * \return the hash function vtable. + */ +static inline const br_hash_class * +br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx) +{ + return ctx->digest_class; +} + +/** + * \brief Type for a provider of entropy seeds. + * + * A "seeder" is a function that is able to obtain random values from + * some source and inject them as entropy seed in a PRNG. A seeder + * shall guarantee that the total entropy of the injected seed is large + * enough to seed a PRNG for purposes of cryptographic key generation + * (i.e. at least 128 bits). + * + * A seeder may report a failure to obtain adequate entropy. Seeders + * shall endeavour to fix themselves transient errors by trying again; + * thus, callers may consider reported errors as permanent. + * + * \param ctx PRNG context to seed. + * \return 1 on success, 0 on error. + */ +typedef int (*br_prng_seeder)(const br_prng_class **ctx); + +/** + * \brief Get a seeder backed by the operating system or hardware. + * + * Get a seeder that feeds on RNG facilities provided by the current + * operating system or hardware. If no such facility is known, then 0 + * is returned. + * + * If `name` is not `NULL`, then `*name` is set to a symbolic string + * that identifies the seeder implementation. If no seeder is returned + * and `name` is not `NULL`, then `*name` is set to a pointer to the + * constant string `"none"`. + * + * \param name receiver for seeder name, or `NULL`. + * \return the system seeder, if available, or 0. + */ +br_prng_seeder br_prng_seeder_system(const char **name); + +/** + * \brief Context for AESCTR_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_aes_gen_ctr_keys sk; + uint32_t cc; +#endif +} br_aesctr_drbg_context; + +/** + * \brief Statically allocated, constant vtable for AESCTR_DRBG. + */ +extern const br_prng_class br_aesctr_drbg_vtable; + +/** + * \brief AESCTR_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The internal AES key is first set to the all-zero key; then, the + * `br_aesctr_drbg_update()` function is called with the provided `seed`. + * The call is performed even if the seed length (`seed_len`) is zero. + * + * The `aesctr` parameter defines the underlying AES/CTR implementation. + * + * \param ctx AESCTR_DRBG context to initialise. + * \param aesctr vtable for the AES/CTR implementation. + * \param seed initial seed (can be `NULL` if `seed_len` is zero). + * \param seed_len initial seed length (in bytes). + */ +void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, + const br_block_ctr_class *aesctr, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with AESCTR_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx AESCTR_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, + void *out, size_t len); + +/** + * \brief Inject additional seed bytes in AESCTR_DRBG. + * + * The provided seed bytes are added into the AESCTR_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx AESCTR_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, + const void *seed, size_t seed_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_rsa.h b/template/sysroot/include/bearssl_rsa.h new file mode 100644 index 0000000..0a069fd --- /dev/null +++ b/template/sysroot/include/bearssl_rsa.h @@ -0,0 +1,1655 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RSA_H__ +#define BR_BEARSSL_RSA_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rsa.h + * + * # RSA + * + * This file documents the RSA implementations provided with BearSSL. + * Note that the SSL engine accesses these implementations through a + * configurable API, so it is possible to, for instance, run a SSL + * server which uses a RSA engine which is not based on this code. + * + * ## Key Elements + * + * RSA public and private keys consist in lists of big integers. All + * such integers are represented with big-endian unsigned notation: + * first byte is the most significant, and the value is positive (so + * there is no dedicated "sign bit"). Public and private key structures + * thus contain, for each such integer, a pointer to the first value byte + * (`unsigned char *`), and a length (`size_t`) which is the number of + * relevant bytes. As a general rule, minimal-length encoding is not + * enforced: values may have extra leading bytes of value 0. + * + * RSA public keys consist in two integers: + * + * - the modulus (`n`); + * - the public exponent (`e`). + * + * RSA private keys, as defined in + * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers: + * + * - the modulus (`n`); + * - the public exponent (`e`); + * - the private exponent (`d`); + * - the first prime factor (`p`); + * - the second prime factor (`q`); + * - the first reduced exponent (`dp`, which is `d` modulo `p-1`); + * - the second reduced exponent (`dq`, which is `d` modulo `q-1`); + * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`). + * + * However, the implementations defined in BearSSL use only five of + * these integers: `p`, `q`, `dp`, `dq` and `iq`. + * + * ## Security Features and Limitations + * + * The implementations contained in BearSSL have the following limitations + * and features: + * + * - They are constant-time. This means that the execution time and + * memory access pattern may depend on the _lengths_ of the private + * key components, but not on their value, nor on the value of + * the operand. Note that this property is not achieved through + * random masking, but "true" constant-time code. + * + * - They support only private keys with two prime factors. RSA private + * keys with three or more prime factors are nominally supported, but + * rarely used; they may offer faster operations, at the expense of + * more code and potentially a reduction in security if there are + * "too many" prime factors. + * + * - The public exponent may have arbitrary length. Of course, it is + * a good idea to keep public exponents small, so that public key + * operations are fast; but, contrary to some widely deployed + * implementations, BearSSL has no problem with public exponents + * longer than 32 bits. + * + * - The two prime factors of the modulus need not have the same length + * (but severely imbalanced factor lengths might reduce security). + * Similarly, there is no requirement that the first factor (`p`) + * be greater than the second factor (`q`). + * + * - Prime factors and modulus must be smaller than a compile-time limit. + * This is made necessary by the use of fixed-size stack buffers, and + * the limit has been adjusted to keep stack usage under 2 kB for the + * RSA operations. Currently, the maximum modulus size is 4096 bits, + * and the maximum prime factor size is 2080 bits. + * + * - The RSA functions themselves do not enforce lower size limits, + * except that which is absolutely necessary for the operation to + * mathematically make sense (e.g. a PKCS#1 v1.5 signature with + * SHA-1 requires a modulus of at least 361 bits). It is up to users + * of this code to enforce size limitations when appropriate (e.g. + * the X.509 validation engine, by default, rejects RSA keys of + * less than 1017 bits). + * + * - Within the size constraints expressed above, arbitrary bit lengths + * are supported. There is no requirement that prime factors or + * modulus have a size multiple of 8 or 16. + * + * - When verifying PKCS#1 v1.5 signatures, both variants of the hash + * function identifying header (with and without the ASN.1 NULL) are + * supported. When producing such signatures, the variant with the + * ASN.1 NULL is used. + * + * ## Implementations + * + * Three RSA implementations are included: + * + * - The **i32** implementation internally represents big integers + * as arrays of 32-bit integers. It is perfunctory and portable, + * but not very efficient. + * + * - The **i31** implementation uses 32-bit integers, each containing + * 31 bits worth of integer data. The i31 implementation is somewhat + * faster than the i32 implementation (the reduced integer size makes + * carry propagation easier) for a similar code footprint, but uses + * very slightly larger stack buffers (about 4% bigger). + * + * - The **i62** implementation is similar to the i31 implementation, + * except that it internally leverages the 64x64->128 multiplication + * opcode. This implementation is available only on architectures + * where such an opcode exists. It is much faster than i31. + * + * - The **i15** implementation uses 16-bit integers, each containing + * 15 bits worth of integer data. Multiplication results fit on + * 32 bits, so this won't use the "widening" multiplication routine + * on ARM Cortex M0/M0+, for much better performance and constant-time + * execution. + */ + +/** + * \brief RSA public key. + * + * The structure references the modulus and the public exponent. Both + * integers use unsigned big-endian representation; extra leading bytes + * of value 0 are allowed. + */ +typedef struct { + /** \brief Modulus. */ + unsigned char *n; + /** \brief Modulus length (in bytes). */ + size_t nlen; + /** \brief Public exponent. */ + unsigned char *e; + /** \brief Public exponent length (in bytes). */ + size_t elen; +} br_rsa_public_key; + +/** + * \brief RSA private key. + * + * The structure references the private factors, reduced private + * exponents, and CRT coefficient. It also contains the bit length of + * the modulus. The big integers use unsigned big-endian representation; + * extra leading bytes of value 0 are allowed. However, the modulus bit + * length (`n_bitlen`) MUST be exact. + */ +typedef struct { + /** \brief Modulus bit length (in bits, exact value). */ + uint32_t n_bitlen; + /** \brief First prime factor. */ + unsigned char *p; + /** \brief First prime factor length (in bytes). */ + size_t plen; + /** \brief Second prime factor. */ + unsigned char *q; + /** \brief Second prime factor length (in bytes). */ + size_t qlen; + /** \brief First reduced private exponent. */ + unsigned char *dp; + /** \brief First reduced private exponent length (in bytes). */ + size_t dplen; + /** \brief Second reduced private exponent. */ + unsigned char *dq; + /** \brief Second reduced private exponent length (in bytes). */ + size_t dqlen; + /** \brief CRT coefficient. */ + unsigned char *iq; + /** \brief CRT coefficient length (in bytes). */ + size_t iqlen; +} br_rsa_private_key; + +/** + * \brief Type for a RSA public key engine. + * + * The public key engine performs the modular exponentiation of the + * provided value with the public exponent. The value is modified in + * place. + * + * The value length (`xlen`) is verified to have _exactly_ the same + * length as the modulus (actual modulus length, without extra leading + * zeros in the modulus representation in memory). If the length does + * not match, then this function returns 0 and `x[]` is unmodified. + * + * It `xlen` is correct, then `x[]` is modified. Returned value is 1 + * on success, 0 on error. Error conditions include an oversized `x[]` + * (the array has the same length as the modulus, but the numerical value + * is not lower than the modulus) and an invalid modulus (e.g. an even + * integer). If an error is reported, then the new contents of `x[]` are + * unspecified. + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA signature verification engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash output length, in bytes. + * + * - The public key. + * + * - An output buffer for the hash value. The caller must still compare + * it with the hash of the data over which the signature is computed. + * + * **Constraints:** + * + * - Hash length MUST be no more than 64 bytes. + * + * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]` + * must have a value in the 0..32 range, inclusive). + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief Type for a RSA signature verification engine (PSS). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same hash function as the one which was + * used to hash the signed message. + * + * - The hashed message (as an array of bytes). + * + * - The PSS salt length (in bytes). + * + * - The public key. + * + * **Constraints:** + * + * - Hash message length MUST be no more than 64 bytes. + * + * Note that, contrary to PKCS#1 v1.5 signature, the hash value of the + * signed data cannot be extracted from the signature; it must be + * provided to the verification function. + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA encryption engine (OAEP). + * + * Parameters are: + * + * - A source of random bytes. The source must be already initialized. + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The public key. + * + * - The destination buffer. Its maximum length (in bytes) is provided; + * if that length is lower than the public key length, then an error + * is reported. + * + * - The source message. + * + * The encrypted message output has exactly the same length as the modulus + * (mathematical length, in bytes, not counting extra leading zeros in the + * modulus representation in the public key). + * + * The source message (`src`, length `src_len`) may overlap with the + * destination buffer (`dst`, length `dst_max_len`). + * + * This function returns the actual encrypted message length, in bytes; + * on error, zero is returned. An error is reported if the output buffer + * is not large enough, or the public is invalid, or the public key + * modulus exceeds the maximum supported RSA size. + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +typedef size_t (*br_rsa_oaep_encrypt)( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief Type for a RSA private key engine. + * + * The `x[]` buffer is modified in place, and its length is inferred from + * the modulus length (`x[]` is assumed to have a length of + * `(sk->n_bitlen+7)/8` bytes). + * + * Returned value is 1 on success, 0 on error. + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_private)(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief Type for a RSA signature generation engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash value computes over the data to sign (its length is + * expressed in bytes). + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash OID and value, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Type for a RSA signature generation engine (PSS). + * + * Parameters are: + * + * - An initialized PRNG for salt generation. If the salt length is + * zero (`salt_len` parameter), then the PRNG is optional (this is + * not the typical case, as the security proof of RSA/PSS is + * tighter when a non-empty salt is used). + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same function as the one used to hash the + * message. + * + * - The hashed message. + * + * - The salt length, in bytes. + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash and salt lengths, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA1 \ + ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A") + +/** + * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA224 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04") + +/** + * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA256 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") + +/** + * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA384 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02") + +/** + * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA512 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") + +/** + * \brief Type for a RSA decryption engine (OAEP). + * + * Parameters are: + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The private key. + * + * - The source and destination buffer. The buffer initially contains + * the encrypted message; the buffer contents are altered, and the + * decrypted message is written at the start of that buffer + * (decrypted message is always shorter than the encrypted message). + * + * If decryption fails in any way, then `*len` is unmodified, and the + * function returns 0. Otherwise, `*len` is set to the decrypted message + * length, and 1 is returned. The implementation is responsible for + * checking that the input message length matches the key modulus length, + * and that the padding is correct. + * + * Implementations MUST use constant-time check of the validity of the + * OAEP padding, at least until the leading byte and hash value have + * been checked. Whether overall decryption worked, and the length of + * the decrypted message, may leak. + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_oaep_decrypt)( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/* + * RSA "i32" engine. Integers are internally represented as arrays of + * 32-bit integers, and the core multiplication primitive is the + * 32x32->64 multiplication. + */ + +/** + * \brief RSA public key engine "i32". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i32" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i32". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i32" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit + * word. This uses slightly more stack space (about 4% more) and code + * space, but it quite faster. + */ + +/** + * \brief RSA public key engine "i31". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i31" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i31". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i31" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i62" engine. Similar to i31, but internal multiplication use + * 64x64->128 multiplications. This is available only on architecture + * that offer such an opcode. + */ + +/** + * \brief RSA public key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get the RSA "i62" implementation (public key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_public br_rsa_i62_public_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (private key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_private br_rsa_i62_private_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_sign br_rsa_i62_pss_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP encryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP decryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void); + +/* + * RSA "i15" engine. Integers are represented as 15-bit integers, so + * the code uses only 32-bit multiplication (no 64-bit result), which + * is vastly faster (and constant-time) on the ARM Cortex M0/M0+. + */ + +/** + * \brief RSA public key engine "i15". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i15" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i15". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i15" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get "default" RSA implementation (public-key operations). + * + * This returns the preferred implementation of RSA (public-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_public br_rsa_public_get_default(void); + +/** + * \brief Get "default" RSA implementation (private-key operations). + * + * This returns the preferred implementation of RSA (private-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_private br_rsa_private_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_sign br_rsa_pss_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP encryption). + * + * This returns the preferred implementation of RSA (OAEP encryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP decryption). + * + * This returns the preferred implementation of RSA (OAEP decryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void); + +/** + * \brief RSA decryption helper, for SSL/TLS. + * + * This function performs the RSA decryption for a RSA-based key exchange + * in a SSL/TLS server. The provided RSA engine is used. The `data` + * parameter points to the value to decrypt, of length `len` bytes. On + * success, the 48-byte pre-master secret is copied into `data`, starting + * at the first byte of that buffer; on error, the contents of `data` + * become indeterminate. + * + * This function first checks that the provided value length (`len`) is + * not lower than 59 bytes, and matches the RSA modulus length; if neither + * of this property is met, then this function returns 0 and the buffer + * is unmodified. + * + * Otherwise, decryption and then padding verification are performed, both + * in constant-time. A decryption error, or a bad padding, or an + * incorrect decrypted value length are reported with a returned value of + * 0; on success, 1 is returned. The caller (SSL server engine) is supposed + * to proceed with a random pre-master secret in case of error. + * + * \param core RSA private key engine. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len length (in bytes) of the data to decrypt. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, + unsigned char *data, size_t len); + +/** + * \brief RSA encryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i15_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i31_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i32_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i62_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief Get buffer size to hold RSA private key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA private key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the private key buffer, in bytes. + */ +#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4)) + +/** + * \brief Get buffer size to hold RSA public key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA public key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the public key buffer, in bytes. + */ +#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3)) + +/** + * \brief Type for RSA key pair generator implementation. + * + * This function generates a new RSA key pair whose modulus has bit + * length `size` bits. The private key elements are written in the + * `kbuf_priv` buffer, and pointer values and length fields to these + * elements are populated in the provided private key structure `sk`. + * Similarly, the public key elements are written in `kbuf_pub`, with + * pointers and lengths set in `pk`. + * + * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the + * private key is set. + * + * If `pubexp` is not zero, then its value will be used as public + * exponent. Valid RSA public exponent values are odd integers + * greater than 1. If `pubexp` is zero, then the public exponent will + * have value 3. + * + * The provided PRNG (`rng_ctx`) must have already been initialized + * and seeded. + * + * Returned value is 1 on success, 0 on error. An error is reported + * if the requested range is outside of the supported key sizes, or + * if an invalid non-zero public exponent value is provided. Supported + * range starts at 512 bits, and up to an implementation-defined + * maximum (by default 4096 bits). Note that key sizes up to 768 bits + * have been broken in practice, and sizes lower than 2048 bits are + * usually considered to be weak and should not be used. + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +typedef uint32_t (*br_rsa_keygen)( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i15" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i15_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i31" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i31_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i62_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief Get the RSA "i62" implementation (key pair generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_keygen br_rsa_i62_keygen_get(void); + +/** + * \brief Get "default" RSA implementation (key pair generation). + * + * This returns the preferred implementation of RSA (key pair generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_keygen br_rsa_keygen_get_default(void); + +/** + * \brief Type for a modulus computing function. + * + * Such a function computes the public modulus from the private key. The + * encoded modulus (unsigned big-endian) is written on `n`, and the size + * (in bytes) is returned. If `n` is `NULL`, then the size is returned but + * the modulus itself is not computed. + * + * If the key size exceeds an internal limit, 0 is returned. + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i15" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i31" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute modulus). + * + * This returns the preferred implementation of RSA (recompute modulus) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void); + +/** + * \brief Type for a public exponent computing function. + * + * Such a function recomputes the public exponent from the private key. + * 0 is returned if any of the following occurs: + * + * - Either `p` or `q` is not equal to 3 modulo 4. + * + * - The public exponent does not fit on 32 bits. + * + * - An internal limit is exceeded. + * + * - The private key is invalid in some way. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds and returns the true + * public exponent. The public exponent is always an odd integer greater + * than 1. + * + * \return the public exponent, or 0. + */ +typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i15" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i31" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute public exponent). + * + * This returns the preferred implementation of RSA (recompute public + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void); + +/** + * \brief Type for a private exponent computing function. + * + * An RSA private key (`br_rsa_private_key`) contains two reduced + * private exponents, which are sufficient to perform private key + * operations. However, standard encoding formats for RSA private keys + * require also a copy of the complete private exponent (non-reduced), + * which this function recomputes. + * + * This function suceeds if all the following conditions hold: + * + * - Both private factors `p` and `q` are equal to 3 modulo 4. + * + * - The provided public exponent `pubexp` is correct, and, in particular, + * is odd, relatively prime to `p-1` and `q-1`, and greater than 1. + * + * - No internal storage limit is exceeded. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds. Note that the API + * restricts the public exponent to a maximum size of 32 bits. + * + * The encoded private exponent is written in `d` (unsigned big-endian + * convention), and the length (in bytes) is returned. If `d` is `NULL`, + * then the exponent is not written anywhere, but the length is still + * returned. On error, 0 is returned. + * + * Not all error conditions are detected when `d` is `NULL`; therefore, the + * returned value shall be checked also when actually producing the value. + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_privexp)(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i15" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i31" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Get "default" RSA implementation (recompute private exponent). + * + * This returns the preferred implementation of RSA (recompute private + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_ssl.h b/template/sysroot/include/bearssl_ssl.h new file mode 100644 index 0000000..e91df47 --- /dev/null +++ b/template/sysroot/include/bearssl_ssl.h @@ -0,0 +1,4296 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_SSL_H__ +#define BR_BEARSSL_SSL_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_prf.h" +#include "bearssl_rand.h" +#include "bearssl_x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ssl.h + * + * # SSL + * + * For an overview of the SSL/TLS API, see [the BearSSL Web + * site](https://www.bearssl.org/api1.html). + * + * The `BR_TLS_*` constants correspond to the standard cipher suites and + * their values in the [IANA + * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). + * + * The `BR_ALERT_*` constants are for standard TLS alert messages. When + * a fatal alert message is sent of received, then the SSL engine context + * status is set to the sum of that alert value (an integer in the 0..255 + * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, + * `BR_ERR_RECV_FATAL_ALERT` for a received alert). + */ + +/** \brief Optimal input buffer size. */ +#define BR_SSL_BUFSIZE_INPUT (16384 + 325) + +/** \brief Optimal output buffer size. */ +#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) + +/** \brief Optimal buffer size for monodirectional engine + (shared input/output buffer). */ +#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT + +/** \brief Optimal buffer size for bidirectional engine + (single buffer split into two separate input/output buffers). */ +#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) + +/* + * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 + * and TLS 1.2). Note that though there is a constant for SSL 3.0, that + * protocol version is not actually supported. + */ + +/** \brief Protocol version: SSL 3.0 (unsupported). */ +#define BR_SSL30 0x0300 +/** \brief Protocol version: TLS 1.0. */ +#define BR_TLS10 0x0301 +/** \brief Protocol version: TLS 1.1. */ +#define BR_TLS11 0x0302 +/** \brief Protocol version: TLS 1.2. */ +#define BR_TLS12 0x0303 + +/* + * Error constants. They are used to report the reason why a context has + * been marked as failed. + * + * Implementation note: SSL-level error codes should be in the 1..31 + * range. The 32..63 range is for certificate decoding and validation + * errors. Received fatal alerts imply an error code in the 256..511 range. + */ + +/** \brief SSL status: no error so far (0). */ +#define BR_ERR_OK 0 + +/** \brief SSL status: caller-provided parameter is incorrect. */ +#define BR_ERR_BAD_PARAM 1 + +/** \brief SSL status: operation requested by the caller cannot be applied + with the current context state (e.g. reading data while outgoing data + is waiting to be sent). */ +#define BR_ERR_BAD_STATE 2 + +/** \brief SSL status: incoming protocol or record version is unsupported. */ +#define BR_ERR_UNSUPPORTED_VERSION 3 + +/** \brief SSL status: incoming record version does not match the expected + version. */ +#define BR_ERR_BAD_VERSION 4 + +/** \brief SSL status: incoming record length is invalid. */ +#define BR_ERR_BAD_LENGTH 5 + +/** \brief SSL status: incoming record is too large to be processed, or + buffer is too small for the handshake message to send. */ +#define BR_ERR_TOO_LARGE 6 + +/** \brief SSL status: decryption found an invalid padding, or the record + MAC is not correct. */ +#define BR_ERR_BAD_MAC 7 + +/** \brief SSL status: no initial entropy was provided, and none can be + obtained from the OS. */ +#define BR_ERR_NO_RANDOM 8 + +/** \brief SSL status: incoming record type is unknown. */ +#define BR_ERR_UNKNOWN_TYPE 9 + +/** \brief SSL status: incoming record or message has wrong type with + regards to the current engine state. */ +#define BR_ERR_UNEXPECTED 10 + +/** \brief SSL status: ChangeCipherSpec message from the peer has invalid + contents. */ +#define BR_ERR_BAD_CCS 12 + +/** \brief SSL status: alert message from the peer has invalid contents + (odd length). */ +#define BR_ERR_BAD_ALERT 13 + +/** \brief SSL status: incoming handshake message decoding failed. */ +#define BR_ERR_BAD_HANDSHAKE 14 + +/** \brief SSL status: ServerHello contains a session ID which is larger + than 32 bytes. */ +#define BR_ERR_OVERSIZED_ID 15 + +/** \brief SSL status: server wants to use a cipher suite that we did + not claim to support. This is also reported if we tried to advertise + a cipher suite that we do not support. */ +#define BR_ERR_BAD_CIPHER_SUITE 16 + +/** \brief SSL status: server wants to use a compression that we did not + claim to support. */ +#define BR_ERR_BAD_COMPRESSION 17 + +/** \brief SSL status: server's max fragment length does not match + client's. */ +#define BR_ERR_BAD_FRAGLEN 18 + +/** \brief SSL status: secure renegotiation failed. */ +#define BR_ERR_BAD_SECRENEG 19 + +/** \brief SSL status: server sent an extension type that we did not + announce, or used the same extension type several times in a single + ServerHello. */ +#define BR_ERR_EXTRA_EXTENSION 20 + +/** \brief SSL status: invalid Server Name Indication contents (when + used by the server, this extension shall be empty). */ +#define BR_ERR_BAD_SNI 21 + +/** \brief SSL status: invalid ServerHelloDone from the server (length + is not 0). */ +#define BR_ERR_BAD_HELLO_DONE 22 + +/** \brief SSL status: internal limit exceeded (e.g. server's public key + is too large). */ +#define BR_ERR_LIMIT_EXCEEDED 23 + +/** \brief SSL status: Finished message from peer does not match the + expected value. */ +#define BR_ERR_BAD_FINISHED 24 + +/** \brief SSL status: session resumption attempt with distinct version + or cipher suite. */ +#define BR_ERR_RESUME_MISMATCH 25 + +/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, + signature algorithm, hash function). */ +#define BR_ERR_INVALID_ALGORITHM 26 + +/** \brief SSL status: invalid signature (on ServerKeyExchange from + server, or in CertificateVerify from client). */ +#define BR_ERR_BAD_SIGNATURE 27 + +/** \brief SSL status: peer's public key does not have the proper type + or is not allowed for requested operation. */ +#define BR_ERR_WRONG_KEY_USAGE 28 + +/** \brief SSL status: client did not send a certificate upon request, + or the client certificate could not be validated. */ +#define BR_ERR_NO_CLIENT_AUTH 29 + +/** \brief SSL status: I/O error or premature close on underlying + transport stream. This error code is set only by the simplified + I/O API ("br_sslio_*"). */ +#define BR_ERR_IO 31 + +/** \brief SSL status: base value for a received fatal alert. + + When a fatal alert is received from the peer, the alert value + is added to this constant. */ +#define BR_ERR_RECV_FATAL_ALERT 256 + +/** \brief SSL status: base value for a sent fatal alert. + + When a fatal alert is sent to the peer, the alert value is added + to this constant. */ +#define BR_ERR_SEND_FATAL_ALERT 512 + +/* ===================================================================== */ + +/** + * \brief Decryption engine for SSL. + * + * When processing incoming records, the SSL engine will use a decryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The decryption engine is responsible for applying decryption, verifying + * MAC, and keeping track of the record sequence number. + */ +typedef struct br_sslrec_in_class_ br_sslrec_in_class; +struct br_sslrec_in_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Test validity of the incoming record length. + * + * This function returns 1 if the announced length for an + * incoming record is valid, 0 otherwise, + * + * \param ctx decryption engine context. + * \param record_len incoming record length. + * \return 1 of a valid length, 0 otherwise. + */ + int (*check_length)(const br_sslrec_in_class *const *ctx, + size_t record_len); + + /** + * \brief Decrypt the incoming record. + * + * This function may assume that the record length is valid + * (it has been previously tested with `check_length()`). + * Decryption is done in place; `*len` is updated with the + * cleartext length, and the address of the first plaintext + * byte is returned. If the record is correct but empty, then + * `*len` is set to 0 and a non-`NULL` pointer is returned. + * + * On decryption/MAC error, `NULL` is returned. + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param payload address of encrypted payload. + * \param len pointer to payload length (updated). + * \return pointer to plaintext, or `NULL` on error. + */ + unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, + int record_type, unsigned version, + void *payload, size_t *len); +}; + +/** + * \brief Encryption engine for SSL. + * + * When building outgoing records, the SSL engine will use an encryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The encryption engine is responsible for applying encryption and MAC, + * and keeping track of the record sequence number. + */ +typedef struct br_sslrec_out_class_ br_sslrec_out_class; +struct br_sslrec_out_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Compute maximum plaintext sizes and offsets. + * + * When this function is called, the `*start` and `*end` + * values contain offsets designating the free area in the + * outgoing buffer for plaintext data; that free area is + * preceded by a 5-byte space which will receive the record + * header. + * + * The `max_plaintext()` function is responsible for adjusting + * both `*start` and `*end` to make room for any record-specific + * header, MAC, padding, and possible split. + * + * \param ctx encryption engine context. + * \param start pointer to start of plaintext offset (updated). + * \param end pointer to start of plaintext offset (updated). + */ + void (*max_plaintext)(const br_sslrec_out_class *const *ctx, + size_t *start, size_t *end); + + /** + * \brief Perform record encryption. + * + * This function encrypts the record. The plaintext address and + * length are provided. Returned value is the start of the + * encrypted record (or sequence of records, if a split was + * performed), _including_ the 5-byte header, and `*len` is + * adjusted to the total size of the record(s), there again + * including the header(s). + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param plaintext address of plaintext. + * \param len pointer to plaintext length (updated). + * \return pointer to start of built record. + */ + unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, + int record_type, unsigned version, + void *plaintext, size_t *len); +}; + +/** + * \brief Context for a no-encryption engine. + * + * The no-encryption engine processes outgoing records during the initial + * handshake, before encryption is applied. + */ +typedef struct { + /** \brief No-encryption engine vtable. */ + const br_sslrec_out_class *vtable; +} br_sslrec_out_clear_context; + +/** \brief Static, constant vtable for the no-encryption engine. */ +extern const br_sslrec_out_class br_sslrec_out_clear_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CBC mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; +struct br_sslrec_in_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC decryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_in_cbc_class **ctx, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for CBC mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; +struct br_sslrec_out_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC encryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_out_cbc_class **ctx, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Context structure for decrypting incoming records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_in_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcdec_class *vtable; + br_aes_gen_cbcdec_keys aes; + br_des_gen_cbcdec_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_in_cbc_context; + +/** + * \brief Static, constant vtable for record decryption with CBC. + */ +extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; + +/** + * \brief Context structure for encrypting outgoing records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_out_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcenc_class *vtable; + br_aes_gen_cbcenc_keys aes; + br_des_gen_cbcenc_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_out_cbc_context; + +/** + * \brief Static, constant vtable for record encryption with CBC. + */ +extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for GCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; +struct br_sslrec_in_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_in_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for GCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; +struct br_sslrec_out_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_out_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Context structure for processing records with GCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_gcm_class *in; + const br_sslrec_out_gcm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctr_class *vtable; + br_aes_gen_ctr_keys aes; + } bc; + br_ghash gh; + unsigned char iv[4]; + unsigned char h[16]; +#endif +} br_sslrec_gcm_context; + +/** + * \brief Static, constant vtable for record decryption with GCM. + */ +extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; + +/** + * \brief Static, constant vtable for record encryption with GCM. + */ +extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; +struct br_sslrec_in_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_in_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Record encryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; +struct br_sslrec_out_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_out_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Context structure for processing records with ChaCha20+Poly1305. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_chapol_class *in; + const br_sslrec_out_chapol_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + unsigned char key[32]; + unsigned char iv[12]; + br_chacha20_run ichacha; + br_poly1305_run ipoly; +#endif +} br_sslrec_chapol_context; + +/** + * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; + +/** + * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; +struct br_sslrec_in_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_in_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Record encryption engine class, for CCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; +struct br_sslrec_out_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_out_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Context structure for processing records with CCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_ccm_class *in; + const br_sslrec_out_ccm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctrcbc_class *vtable; + br_aes_gen_ctrcbc_keys aes; + } bc; + unsigned char iv[4]; + size_t tag_len; +#endif +} br_sslrec_ccm_context; + +/** + * \brief Static, constant vtable for record decryption with CCM. + */ +extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; + +/** + * \brief Static, constant vtable for record encryption with CCM. + */ +extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; + +/* ===================================================================== */ + +/** + * \brief Type for session parameters, to be saved for session resumption. + */ +typedef struct { + /** \brief Session ID buffer. */ + unsigned char session_id[32]; + /** \brief Session ID length (in bytes, at most 32). */ + unsigned char session_id_len; + /** \brief Protocol version. */ + uint16_t version; + /** \brief Cipher suite. */ + uint16_t cipher_suite; + /** \brief Master secret. */ + unsigned char master_secret[48]; +} br_ssl_session_parameters; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Maximum number of cipher suites supported by a client or server. + */ +#define BR_MAX_CIPHER_SUITES 48 +#endif + +/** + * \brief Context structure for SSL engine. + * + * This strucuture is common to the client and server; both the client + * context (`br_ssl_client_context`) and the server context + * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their + * first field. + * + * The engine context manages records, including alerts, closures, and + * transitions to new encryption/MAC algorithms. Processing of handshake + * records is delegated to externally provided code. This structure + * should not be used directly. + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* + * The error code. When non-zero, then the state is "failed" and + * no I/O may occur until reset. + */ + int err; + + /* + * Configured I/O buffers. They are either disjoint, or identical. + */ + unsigned char *ibuf, *obuf; + size_t ibuf_len, obuf_len; + + /* + * Maximum fragment length applies to outgoing records; incoming + * records can be processed as long as they fit in the input + * buffer. It is guaranteed that incoming records at least as big + * as max_frag_len can be processed. + */ + uint16_t max_frag_len; + unsigned char log_max_frag_len; + unsigned char peer_log_max_frag_len; + + /* + * Buffering management registers. + */ + size_t ixa, ixb, ixc; + size_t oxa, oxb, oxc; + unsigned char iomode; + unsigned char incrypt; + + /* + * Shutdown flag: when set to non-zero, incoming record bytes + * will not be accepted anymore. This is used after a close_notify + * has been received: afterwards, the engine no longer claims that + * it could receive bytes from the transport medium. + */ + unsigned char shutdown_recv; + + /* + * 'record_type_in' is set to the incoming record type when the + * record header has been received. + * 'record_type_out' is used to make the next outgoing record + * header when it is ready to go. + */ + unsigned char record_type_in, record_type_out; + + /* + * When a record is received, its version is extracted: + * -- if 'version_in' is 0, then it is set to the received version; + * -- otherwise, if the received version is not identical to + * the 'version_in' contents, then a failure is reported. + * + * This implements the SSL requirement that all records shall + * use the negotiated protocol version, once decided (in the + * ServerHello). It is up to the handshake handler to adjust this + * field when necessary. + */ + uint16_t version_in; + + /* + * 'version_out' is used when the next outgoing record is ready + * to go. + */ + uint16_t version_out; + + /* + * Record handler contexts. + */ + union { + const br_sslrec_in_class *vtable; + br_sslrec_in_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } in; + union { + const br_sslrec_out_class *vtable; + br_sslrec_out_clear_context clear; + br_sslrec_out_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } out; + + /* + * The "application data" flag. Value: + * 0 handshake is in process, no application data acceptable + * 1 application data can be sent and received + * 2 closing, no application data can be sent, but some + * can still be received (and discarded) + */ + unsigned char application_data; + + /* + * Context RNG. + * + * rng_init_done is initially 0. It is set to 1 when the + * basic structure of the RNG is set, and 2 when some + * entropy has been pushed in. The value 2 marks the RNG + * as "properly seeded". + * + * rng_os_rand_done is initially 0. It is set to 1 when + * some seeding from the OS or hardware has been attempted. + */ + br_hmac_drbg_context rng; + int rng_init_done; + int rng_os_rand_done; + + /* + * Supported minimum and maximum versions, and cipher suites. + */ + uint16_t version_min; + uint16_t version_max; + uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; + unsigned char suites_num; + + /* + * For clients, the server name to send as a SNI extension. For + * servers, the name received in the SNI extension (if any). + */ + char server_name[256]; + + /* + * "Security parameters". These are filled by the handshake + * handler, and used when switching encryption state. + */ + unsigned char client_random[32]; + unsigned char server_random[32]; + br_ssl_session_parameters session; + + /* + * ECDHE elements: curve and point from the peer. The server also + * uses that buffer for the point to send to the client. + */ + unsigned char ecdhe_curve; + unsigned char ecdhe_point[133]; + unsigned char ecdhe_point_len; + + /* + * Secure renegotiation (RFC 5746): 'reneg' can be: + * 0 first handshake (server support is not known) + * 1 peer does not support secure renegotiation + * 2 peer supports secure renegotiation + * + * The saved_finished buffer contains the client and the + * server "Finished" values from the last handshake, in + * that order (12 bytes each). + */ + unsigned char reneg; + unsigned char saved_finished[24]; + + /* + * Behavioural flags. + */ + uint32_t flags; + + /* + * Context variables for the handshake processor. The 'pad' must + * be large enough to accommodate an RSA-encrypted pre-master + * secret, or an RSA signature; since we want to support up to + * RSA-4096, this means at least 512 bytes. (Other pad usages + * require its length to be at least 256.) + */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + unsigned char pad[512]; + unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; + size_t hlen_in, hlen_out; + void (*hsrun)(void *ctx); + + /* + * The 'action' value communicates OOB information between the + * engine and the handshake processor. + * + * From the engine: + * 0 invocation triggered by I/O + * 1 invocation triggered by explicit close + * 2 invocation triggered by explicit renegotiation + */ + unsigned char action; + + /* + * State for alert messages. Value is either 0, or the value of + * the alert level byte (level is either 1 for warning, or 2 for + * fatal; we convert all other values to 'fatal'). + */ + unsigned char alert; + + /* + * Closure flags. This flag is set when a close_notify has been + * received from the peer. + */ + unsigned char close_received; + + /* + * Multi-hasher for the handshake messages. The handshake handler + * is responsible for resetting it when appropriate. + */ + br_multihash_context mhash; + + /* + * Pointer to the X.509 engine. The engine is supposed to be + * already initialized. It is used to validate the peer's + * certificate. + */ + const br_x509_class **x509ctx; + + /* + * Certificate chain to send. This is used by both client and + * server, when they send their respective Certificate messages. + * If chain_len is 0, then chain may be NULL. + */ + const br_x509_certificate *chain; + size_t chain_len; + const unsigned char *cert_cur; + size_t cert_len; + + /* + * List of supported protocol names (ALPN extension). If unset, + * (number of names is 0), then: + * - the client sends no ALPN extension; + * - the server ignores any incoming ALPN extension. + * + * Otherwise: + * - the client sends an ALPN extension with all the names; + * - the server selects the first protocol in its list that + * the client also supports, or fails (fatal alert 120) + * if the client sends an ALPN extension and there is no + * match. + * + * The 'selected_protocol' field contains 1+n if the matching + * name has index n in the list (the value is 0 if no match was + * performed, e.g. the peer did not send an ALPN extension). + */ + const char **protocol_names; + uint16_t protocol_names_num; + uint16_t selected_protocol; + + /* + * Pointers to implementations; left to NULL for unsupported + * functions. For the raw hash functions, implementations are + * referenced from the multihasher (mhash field). + */ + br_tls_prf_impl prf10; + br_tls_prf_impl prf_sha256; + br_tls_prf_impl prf_sha384; + const br_block_cbcenc_class *iaes_cbcenc; + const br_block_cbcdec_class *iaes_cbcdec; + const br_block_ctr_class *iaes_ctr; + const br_block_ctrcbc_class *iaes_ctrcbc; + const br_block_cbcenc_class *ides_cbcenc; + const br_block_cbcdec_class *ides_cbcdec; + br_ghash ighash; + br_chacha20_run ichacha; + br_poly1305_run ipoly; + const br_sslrec_in_cbc_class *icbc_in; + const br_sslrec_out_cbc_class *icbc_out; + const br_sslrec_in_gcm_class *igcm_in; + const br_sslrec_out_gcm_class *igcm_out; + const br_sslrec_in_chapol_class *ichapol_in; + const br_sslrec_out_chapol_class *ichapol_out; + const br_sslrec_in_ccm_class *iccm_in; + const br_sslrec_out_ccm_class *iccm_out; + const br_ec_impl *iec; + br_rsa_pkcs1_vrfy irsavrfy; + br_ecdsa_vrfy iecdsa; +#endif +} br_ssl_engine_context; + +/** + * \brief Get currently defined engine behavioural flags. + * + * \param cc SSL engine context. + * \return the flags. + */ +static inline uint32_t +br_ssl_engine_get_flags(br_ssl_engine_context *cc) +{ + return cc->flags; +} + +/** + * \brief Set all engine behavioural flags. + * + * \param cc SSL engine context. + * \param flags new value for all flags. + */ +static inline void +br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags = flags; +} + +/** + * \brief Set some engine behavioural flags. + * + * The flags set in the `flags` parameter are set in the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags additional set flags. + */ +static inline void +br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags |= flags; +} + +/** + * \brief Clear some engine behavioural flags. + * + * The flags set in the `flags` parameter are cleared from the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags flags to remove. + */ +static inline void +br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags &= ~flags; +} + +/** + * \brief Behavioural flag: enforce server preferences. + * + * If this flag is set, then the server will enforce its own cipher suite + * preference order; otherwise, it follows the client preferences. + */ +#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) + +/** + * \brief Behavioural flag: disable renegotiation. + * + * If this flag is set, then renegotiations are rejected unconditionally: + * they won't be honoured if asked for programmatically, and requests from + * the peer are rejected. + */ +#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) + +/** + * \brief Behavioural flag: tolerate lack of client authentication. + * + * If this flag is set in a server and the server requests a client + * certificate, but the authentication fails (the client does not send + * a certificate, or the client's certificate chain cannot be validated), + * then the connection keeps on. Without this flag, a failed client + * authentication terminates the connection. + * + * Notes: + * + * - If the client's certificate can be validated and its public key is + * supported, then a wrong signature value terminates the connection + * regardless of that flag. + * + * - If using full-static ECDH, then a failure to validate the client's + * certificate prevents the handshake from succeeding. + */ +#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) + +/** + * \brief Behavioural flag: fail on application protocol mismatch. + * + * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) + * allows the client to send a list of application protocol names, and + * the server to select one. A mismatch is one of the following occurrences: + * + * - On the client: the client sends a list of names, the server + * responds with a protocol name which is _not_ part of the list of + * names sent by the client. + * + * - On the server: the client sends a list of names, and the server + * is also configured with a list of names, but there is no common + * protocol name between the two lists. + * + * Normal behaviour in case of mismatch is to report no matching name + * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. + * If the flag is set, then a mismatch implies a protocol failure (if + * the mismatch is detected by the server, it will send a fatal alert). + * + * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` + * may still return `NULL` if the client or the server does not send an + * ALPN extension at all. + */ +#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) + +/** + * \brief Set the minimum and maximum supported protocol versions. + * + * The two provided versions MUST be supported by the implementation + * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower + * than `version_min`. + * + * \param cc SSL engine context. + * \param version_min minimum supported TLS version. + * \param version_max maximum supported TLS version. + */ +static inline void +br_ssl_engine_set_versions(br_ssl_engine_context *cc, + unsigned version_min, unsigned version_max) +{ + cc->version_min = (uint16_t)version_min; + cc->version_max = (uint16_t)version_max; +} + +/** + * \brief Set the list of cipher suites advertised by this context. + * + * The provided array is copied into the context. It is the caller + * responsibility to ensure that all provided suites will be supported + * by the context. The engine context has enough room to receive _all_ + * suites supported by the implementation. The provided array MUST NOT + * contain duplicates. + * + * If the engine is for a client, the "signaling" pseudo-cipher suite + * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the + * calling application is performing a voluntary downgrade (voluntary + * downgrades are not recommended, but if such a downgrade is done, then + * adding the fallback pseudo-suite is a good idea). + * + * \param cc SSL engine context. + * \param suites cipher suites. + * \param suites_num number of cipher suites. + */ +void br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num); + +/** + * \brief Set the X.509 engine. + * + * The caller shall ensure that the X.509 engine is properly initialised. + * + * \param cc SSL engine context. + * \param x509ctx X.509 certificate validation context. + */ +static inline void +br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) +{ + cc->x509ctx = x509ctx; +} + +/** + * \brief Set the supported protocol names. + * + * Protocol names are part of the ALPN extension ([RFC + * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a + * character string, containing no more than 255 characters (256 with the + * terminating zero). When names are set, then: + * + * - The client will send an ALPN extension, containing the names. If + * the server responds with an ALPN extension, the client will verify + * that the response contains one of its name, and report that name + * through `br_ssl_engine_get_selected_protocol()`. + * + * - The server will parse incoming ALPN extension (from clients), and + * try to find a common protocol; if none is found, the connection + * is aborted with a fatal alert. On match, a response ALPN extension + * is sent, and name is reported through + * `br_ssl_engine_get_selected_protocol()`. + * + * The provided array is linked in, and must remain valid while the + * connection is live. + * + * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters + * (excluding the terminating 0). + * + * \param ctx SSL engine context. + * \param names list of protocol names (zero-terminated). + * \param num number of protocol names (MUST be 1 or more). + */ +static inline void +br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, + const char **names, size_t num) +{ + ctx->protocol_names = names; + ctx->protocol_names_num = (uint16_t)num; +} + +/** + * \brief Get the selected protocol. + * + * If this context was initialised with a non-empty list of protocol + * names, and both client and server sent ALPN extensions during the + * handshake, and a common name was found, then that name is returned. + * Otherwise, `NULL` is returned. + * + * The returned pointer is one of the pointers provided to the context + * with `br_ssl_engine_set_protocol_names()`. + * + * \return the selected protocol, or `NULL`. + */ +static inline const char * +br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) +{ + unsigned k; + + k = ctx->selected_protocol; + return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; +} + +/** + * \brief Set a hash function implementation (by ID). + * + * Hash functions set with this call will be used for SSL/TLS specific + * usages, not X.509 certificate validation. Only "standard" hash functions + * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` + * is `NULL`, then the hash function support is removed, not added. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_hash(br_ssl_engine_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Get a hash function implementation (by ID). + * + * This function retrieves a hash function implementation which was + * set with `br_ssl_engine_set_hash()`. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \return the hash function implementation (or `NULL`). + */ +static inline const br_hash_class * +br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) +{ + return br_multihash_getimpl(&ctx->mhash, id); +} + +/** + * \brief Set the PRF implementation (for TLS 1.0 and 1.1). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the PRF used in TLS 1.0 and 1.1. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf10 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-256 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha256 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-384 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha384 = impl; +} + +/** + * \brief Set the AES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc AES/CBC encryption implementation (or `NULL`). + * \param impl_dec AES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->iaes_cbcenc = impl_enc; + cc->iaes_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, + const br_block_ctr_class *impl) +{ + cc->iaes_ctr = impl; +} + +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + +/** + * \brief Set the DES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc DES/CBC encryption implementation (or `NULL`). + * \param impl_dec DES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->ides_cbcenc = impl_enc; + cc->ides_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the GHASH implementation (used in GCM mode). + * + * \param cc SSL engine context. + * \param impl GHASH implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) +{ + cc->ighash = impl; +} + +/** + * \brief Set the ChaCha20 implementation. + * + * \param cc SSL engine context. + * \param ichacha ChaCha20 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, + br_chacha20_run ichacha) +{ + cc->ichacha = ichacha; +} + +/** + * \brief Set the Poly1305 implementation. + * + * \param cc SSL engine context. + * \param ipoly Poly1305 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, + br_poly1305_run ipoly) +{ + cc->ipoly = ipoly; +} + +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR+CBC implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, + const br_block_ctrcbc_class *impl) +{ + cc->iaes_ctrcbc = impl; +} + +/** + * \brief Set the "default" implementations for AES/CCM. + * + * This function configures in the engine the AES/CTR+CBC + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for CCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); + +/** + * \brief Set the record encryption and decryption engines for CBC + HMAC. + * + * \param cc SSL engine context. + * \param impl_in record CBC decryption implementation (or `NULL`). + * \param impl_out record CBC encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_cbc(br_ssl_engine_context *cc, + const br_sslrec_in_cbc_class *impl_in, + const br_sslrec_out_cbc_class *impl_out) +{ + cc->icbc_in = impl_in; + cc->icbc_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for GCM. + * + * \param cc SSL engine context. + * \param impl_in record GCM decryption implementation (or `NULL`). + * \param impl_out record GCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_gcm(br_ssl_engine_context *cc, + const br_sslrec_in_gcm_class *impl_in, + const br_sslrec_out_gcm_class *impl_out) +{ + cc->igcm_in = impl_in; + cc->igcm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for CCM. + * + * \param cc SSL engine context. + * \param impl_in record CCM decryption implementation (or `NULL`). + * \param impl_out record CCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ccm(br_ssl_engine_context *cc, + const br_sslrec_in_ccm_class *impl_in, + const br_sslrec_out_ccm_class *impl_out) +{ + cc->iccm_in = impl_in; + cc->iccm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for + * ChaCha20+Poly1305. + * + * \param cc SSL engine context. + * \param impl_in record ChaCha20 decryption implementation (or `NULL`). + * \param impl_out record ChaCha20 encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chapol(br_ssl_engine_context *cc, + const br_sslrec_in_chapol_class *impl_in, + const br_sslrec_out_chapol_class *impl_out) +{ + cc->ichapol_in = impl_in; + cc->ichapol_out = impl_out; +} + +/** + * \brief Set the EC implementation. + * + * The elliptic curve implementation will be used for ECDH and ECDHE + * cipher suites, and for ECDSA support. + * + * \param cc SSL engine context. + * \param iec EC implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) +{ + cc->iec = iec; +} + +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + +/** + * \brief Set the RSA signature verification implementation. + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, and that certificate contains a RSA key). + * + * \param cc SSL engine context. + * \param irsavrfy RSA signature verification implementation. + */ +static inline void +br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) +{ + cc->irsavrfy = irsavrfy; +} + +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + +/* + * \brief Set the ECDSA implementation (signature verification). + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, that certificate contains an EC key, + * and full-static ECDH is not used). + * + * The ECDSA implementation will use the EC core implementation configured + * in the engine context. + * + * \param cc client context. + * \param iecdsa ECDSA verification implementation. + */ +static inline void +br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) +{ + cc->iecdsa = iecdsa; +} + +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + +/** + * \brief Set the I/O buffer for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * The provided buffer will be used as long as the engine context is + * used. The caller is responsible for keeping it available. + * + * If `bidi` is 0, then the engine will operate in half-duplex mode + * (it won't be able to send data while there is unprocessed incoming + * data in the buffer, and it won't be able to receive data while there + * is unsent data in the buffer). The optimal buffer size in half-duplex + * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra + * bytes are ignored. If the buffer is smaller, then this limits the + * capacity of the engine to support all allowed record sizes. + * + * If `bidi` is 1, then the engine will split the buffer into two + * parts, for separate handling of outgoing and incoming data. This + * enables full-duplex processing, but requires more RAM. The optimal + * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the + * buffer is larger, then extra bytes are ignored. If the buffer is + * smaller, then the split will favour the incoming part, so that + * interoperability is maximised. + * + * \param cc SSL engine context + * \param iobuf I/O buffer. + * \param iobuf_len I/O buffer length (in bytes). + * \param bidi non-zero for full-duplex mode. + */ +void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, + void *iobuf, size_t iobuf_len, int bidi); + +/** + * \brief Set the I/O buffers for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * This function is similar to `br_ssl_engine_set_buffer()`, except + * that it enforces full-duplex mode, and the two I/O buffers are + * provided as separate chunks. + * + * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` + * evaluate to the optimal (maximum) sizes for the input and output + * buffer, respectively. + * + * \param cc SSL engine context + * \param ibuf input buffer. + * \param ibuf_len input buffer length (in bytes). + * \param obuf output buffer. + * \param obuf_len output buffer length (in bytes). + */ +void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); + +/** + * \brief Inject some "initial entropy" in the context. + * + * This entropy will be added to what can be obtained from the + * underlying operating system, if that OS is supported. + * + * This function may be called several times; all injected entropy chunks + * are cumulatively mixed. + * + * If entropy gathering from the OS is supported and compiled in, then this + * step is optional. Otherwise, it is mandatory to inject randomness, and + * the caller MUST take care to push (as one or several successive calls) + * enough entropy to achieve cryptographic resistance (at least 80 bits, + * preferably 128 or more). The engine will report an error if no entropy + * was provided and none can be obtained from the OS. + * + * Take care that this function cannot assess the cryptographic quality of + * the provided bytes. + * + * In all generality, "entropy" must here be considered to mean "that + * which the attacker cannot predict". If your OS/architecture does not + * have a suitable source of randomness, then you can make do with the + * combination of a large enough secret value (possibly a copy of an + * asymmetric private key that you also store on the system) AND a + * non-repeating value (e.g. current time, provided that the local clock + * cannot be reset or altered by the attacker). + * + * \param cc SSL engine context. + * \param data extra entropy to inject. + * \param len length of the extra data (in bytes). + */ +void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len); + +/** + * \brief Get the "server name" in this engine. + * + * For clients, this is the name provided with `br_ssl_client_reset()`; + * for servers, this is the name received from the client as part of the + * ClientHello message. If there is no such name (e.g. the client did + * not send an SNI extension) then the returned string is empty + * (returned pointer points to a byte of value 0). + * + * The returned pointer refers to a buffer inside the context, which may + * be overwritten as part of normal SSL activity (even within the same + * connection, if a renegotiation occurs). + * + * \param cc SSL engine context. + * \return the server name (possibly empty). + */ +static inline const char * +br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) +{ + return cc->server_name; +} + +/** + * \brief Get the protocol version. + * + * This function returns the protocol version that is used by the + * engine. That value is set after sending (for a server) or receiving + * (for a client) the ServerHello message. + * + * \param cc SSL engine context. + * \return the protocol version. + */ +static inline unsigned +br_ssl_engine_get_version(const br_ssl_engine_context *cc) +{ + return cc->session.version; +} + +/** + * \brief Get a copy of the session parameters. + * + * The session parameters are filled during the handshake, so this + * function shall not be called before completion of the handshake. + * The initial handshake is completed when the context first allows + * application data to be injected. + * + * This function copies the current session parameters into the provided + * structure. Beware that the session parameters include the master + * secret, which is sensitive data, to handle with great care. + * + * \param cc SSL engine context. + * \param pp destination structure for the session parameters. + */ +static inline void +br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, + br_ssl_session_parameters *pp) +{ + memcpy(pp, &cc->session, sizeof *pp); +} + +/** + * \brief Set the session parameters to the provided values. + * + * This function is meant to be used in the client, before doing a new + * handshake; a session resumption will be attempted with these + * parameters. In the server, this function has no effect. + * + * \param cc SSL engine context. + * \param pp source structure for the session parameters. + */ +static inline void +br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, + const br_ssl_session_parameters *pp) +{ + memcpy(&cc->session, pp, sizeof *pp); +} + +/** + * \brief Get identifier for the curve used for key exchange. + * + * If the cipher suite uses ECDHE, then this function returns the + * identifier for the curve used for transient parameters. This is + * defined during the course of the handshake, when the ServerKeyExchange + * is sent (on the server) or received (on the client). If the + * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key + * exchange), then this value is indeterminate. + * + * @param cc SSL engine context. + * @return the ECDHE curve identifier. + */ +static inline int +br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) +{ + return cc->ecdhe_curve; +} + +/** + * \brief Get the current engine state. + * + * An SSL engine (client or server) has, at any time, a state which is + * the combination of zero, one or more of these flags: + * + * - `BR_SSL_CLOSED` + * + * Engine is finished, no more I/O (until next reset). + * + * - `BR_SSL_SENDREC` + * + * Engine has some bytes to send to the peer. + * + * - `BR_SSL_RECVREC` + * + * Engine expects some bytes from the peer. + * + * - `BR_SSL_SENDAPP` + * + * Engine may receive application data to send (or flush). + * + * - `BR_SSL_RECVAPP` + * + * Engine has obtained some application data from the peer, + * that should be read by the caller. + * + * If no flag at all is set (state value is 0), then the engine is not + * fully initialised yet. + * + * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag + * is set. To distinguish between a normal closure and an error, use + * `br_ssl_engine_last_error()`. + * + * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually + * exclusive: the input buffer, at any point, either accumulates + * plaintext data, or contains an assembled record that is being sent. + * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. + * This may change in a future library version. + * + * \param cc SSL engine context. + * \return the current engine state. + */ +unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); + +/** \brief SSL engine state: closed or failed. */ +#define BR_SSL_CLOSED 0x0001 +/** \brief SSL engine state: record data is ready to be sent to the peer. */ +#define BR_SSL_SENDREC 0x0002 +/** \brief SSL engine state: engine may receive records from the peer. */ +#define BR_SSL_RECVREC 0x0004 +/** \brief SSL engine state: engine may accept application data to send. */ +#define BR_SSL_SENDAPP 0x0008 +/** \brief SSL engine state: engine has received application data. */ +#define BR_SSL_RECVAPP 0x0010 + +/** + * \brief Get the engine error indicator. + * + * The error indicator is `BR_ERR_OK` (0) if no error was encountered + * since the last call to `br_ssl_client_reset()` or + * `br_ssl_server_reset()`. Other status values are "sticky": they + * remain set, and prevent all I/O activity, until cleared. Only the + * reset calls clear the error indicator. + * + * \param cc SSL engine context. + * \return 0, or a non-zero error code. + */ +static inline int +br_ssl_engine_last_error(const br_ssl_engine_context *cc) +{ + return cc->err; +} + +/* + * There are four I/O operations, each identified by a symbolic name: + * + * sendapp inject application data in the engine + * recvapp retrieving application data from the engine + * sendrec sending records on the transport medium + * recvrec receiving records from the transport medium + * + * Terminology works thus: in a layered model where the SSL engine sits + * between the application and the network, "send" designates operations + * where bytes flow from application to network, and "recv" for the + * reverse operation. Application data (the plaintext that is to be + * conveyed through SSL) is "app", while encrypted records are "rec". + * Note that from the SSL engine point of view, "sendapp" and "recvrec" + * designate bytes that enter the engine ("inject" operation), while + * "recvapp" and "sendrec" designate bytes that exit the engine + * ("extract" operation). + * + * For the operation 'xxx', two functions are defined: + * + * br_ssl_engine_xxx_buf + * Returns a pointer and length to the buffer to use for that + * operation. '*len' is set to the number of bytes that may be read + * from the buffer (extract operation) or written to the buffer + * (inject operation). If no byte may be exchanged for that operation + * at that point, then '*len' is set to zero, and NULL is returned. + * The engine state is unmodified by this call. + * + * br_ssl_engine_xxx_ack + * Informs the engine that 'len' bytes have been read from the buffer + * (extract operation) or written to the buffer (inject operation). + * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed + * that which was obtained from a preceding br_ssl_engine_xxx_buf() + * call. + */ + +/** + * \brief Get buffer for application data to send. + * + * If the engine is ready to accept application data to send to the + * peer, then this call returns a pointer to the buffer where such + * data shall be written, and its length is written in `*len`. + * Otherwise, `*len` is set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data output buffer length, or 0. + * \return the application data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new application data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_sendapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for received application data. + * + * If the engine has received application data from the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data input buffer length, or 0. + * \return the application data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some received application data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_recvapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for record data to send. + * + * If the engine has prepared some records to send to the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data output buffer length, or 0. + * \return the record data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some sent record data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_sendrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for incoming records. + * + * If the engine is ready to accept records from the peer, then this + * call returns a pointer to the buffer where such data shall be + * written, and its length is written in `*len`. Otherwise, `*len` is + * set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data input buffer length, or 0. + * \return the record data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new record data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_recvrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Flush buffered application data. + * + * If some application data has been buffered in the engine, then wrap + * it into a record and mark it for sending. If no application data has + * been buffered but the engine would be ready to accept some, AND the + * `force` parameter is non-zero, then an empty record is assembled and + * marked for sending. In all other cases, this function does nothing. + * + * Empty records are technically legal, but not all existing SSL/TLS + * implementations support them. Empty records can be useful as a + * transparent "keep-alive" mechanism to maintain some low-level + * network activity. + * + * \param cc SSL engine context. + * \param force non-zero to force sending an empty record. + */ +void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); + +/** + * \brief Initiate a closure. + * + * If, at that point, the context is open and in ready state, then a + * `close_notify` alert is assembled and marked for sending; this + * triggers the closure protocol. Otherwise, no such alert is assembled. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_close(br_ssl_engine_context *cc); + +/** + * \brief Initiate a renegotiation. + * + * If the engine is failed or closed, or if the peer is known not to + * support secure renegotiation (RFC 5746), or if renegotiations have + * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there + * is buffered incoming application data, then this function returns 0 + * and nothing else happens. + * + * Otherwise, this function returns 1, and a renegotiation attempt is + * triggered (if a handshake is already ongoing at that point, then + * no new handshake is triggered). + * + * \param cc SSL engine context. + * \return 1 on success, 0 on error. + */ +int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); + +/** + * \brief Export key material from a connected SSL engine (RFC 5705). + * + * This calls compute a secret key of arbitrary length from the master + * secret of a connected SSL engine. If the provided context is not + * currently in "application data" state (initial handshake is not + * finished, another handshake is ongoing, or the connection failed or + * was closed), then this function returns 0. Otherwise, a secret key of + * length `len` bytes is computed and written in the buffer pointed to + * by `dst`, and 1 is returned. + * + * The computed key follows the specification described in RFC 5705. + * That RFC includes two key computations, with and without a "context + * value". If `context` is `NULL`, then the variant without context is + * used; otherwise, the `context_len` bytes located at the address + * pointed to by `context` are used in the computation. Note that it + * is possible to have a "with context" key with a context length of + * zero bytes, by setting `context` to a non-`NULL` value but + * `context_len` to 0. + * + * When context bytes are used, the context length MUST NOT exceed + * 65535 bytes. + * + * \param cc SSL engine context. + * \param dst destination buffer for exported key. + * \param len exported key length (in bytes). + * \param label disambiguation label. + * \param context context value (or `NULL`). + * \param context_len context length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len); + +/* + * Pre-declaration for the SSL client context. + */ +typedef struct br_ssl_client_context_ br_ssl_client_context; + +/** + * \brief Type for the client certificate, if requested by the server. + */ +typedef struct { + /** + * \brief Authentication type. + * + * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` + * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). + */ + int auth_type; + + /** + * \brief Hash function for computing the CertificateVerify. + * + * This is the symbolic identifier for the hash function that + * will be used to produce the hash of handshake messages, to + * be signed into the CertificateVerify. For full static ECDH + * (client and server certificates are both EC in the same + * curve, and static ECDH is used), this value is set to -1. + * + * Take care that with TLS 1.0 and 1.1, that value MUST match + * the protocol requirements: value must be 0 (MD5+SHA-1) for + * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only + * TLS 1.2 allows for other hash functions. + */ + int hash_id; + + /** + * \brief Certificate chain to send to the server. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The client + * code does not try to decode these elements. If there is no + * chain to send to the server, then this pointer shall be + * set to `NULL`. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + * + * If there is no chain to send to the server, then this value + * shall be set to 0. + */ + size_t chain_len; + +} br_ssl_client_certificate; + +/* + * Note: the constants below for signatures match the TLS constants. + */ + +/** \brief Client authentication type: static ECDH. */ +#define BR_AUTH_ECDH 0 +/** \brief Client authentication type: RSA signature. */ +#define BR_AUTH_RSA 1 +/** \brief Client authentication type: ECDSA signature. */ +#define BR_AUTH_ECDSA 3 + +/** + * \brief Class type for a certificate handler (client side). + * + * A certificate handler selects a client certificate chain to send to + * the server, upon explicit request from that server. It receives + * the list of trust anchor DN from the server, and supported types + * of certificates and signatures, and returns the chain to use. It + * is also invoked to perform the corresponding private key operation + * (a signature, or an ECDH computation). + * + * The SSL client engine will first push the trust anchor DN with + * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` + * and `end_name_list()`. Then it will call `choose()`, to select the + * actual chain (and signature/hash algorithms). Finally, it will call + * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. + */ +typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; +struct br_ssl_client_certificate_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Begin reception of a list of trust anchor names. This + * is called while parsing the incoming CertificateRequest. + * + * \param pctx certificate handler context. + */ + void (*start_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Begin reception of a new trust anchor name. + * + * The total encoded name length is provided; it is less than + * 65535 bytes. + * + * \param pctx certificate handler context. + * \param len encoded name length (in bytes). + */ + void (*start_name)(const br_ssl_client_certificate_class **pctx, + size_t len); + + /** + * \brief Receive some more bytes for the current trust anchor name. + * + * The provided reference (`data`) points to a transient buffer + * they may be reused as soon as this function returns. The chunk + * length (`len`) is never zero. + * + * \param pctx certificate handler context. + * \param data anchor name chunk. + * \param len anchor name chunk length (in bytes). + */ + void (*append_name)(const br_ssl_client_certificate_class **pctx, + const unsigned char *data, size_t len); + + /** + * \brief End current trust anchor name. + * + * This function is called when all the encoded anchor name data + * has been provided. + * + * \param pctx certificate handler context. + */ + void (*end_name)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief End list of trust anchor names. + * + * This function is called when all the anchor names in the + * CertificateRequest message have been obtained. + * + * \param pctx certificate handler context. + */ + void (*end_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Select client certificate and algorithms. + * + * This callback function shall fill the provided `choices` + * structure with the selected algorithms and certificate chain. + * The `hash_id`, `chain` and `chain_len` fields must be set. If + * the client cannot or does not wish to send a certificate, + * then it shall set `chain` to `NULL` and `chain_len` to 0. + * + * The `auth_types` parameter describes the authentication types, + * signature algorithms and hash functions that are supported by + * both the client context and the server, and compatible with + * the current protocol version. This is a bit field with the + * following contents: + * + * - If RSA signatures with hash function x are supported, then + * bit x is set. + * + * - If ECDSA signatures with hash function x are supported, + * then bit 8+x is set. + * + * - If static ECDH is supported, with a RSA-signed certificate, + * then bit 16 is set. + * + * - If static ECDH is supported, with an ECDSA-signed certificate, + * then bit 17 is set. + * + * Notes: + * + * - When using TLS 1.0 or 1.1, the hash function for RSA + * signatures is always the special MD5+SHA-1 (id 0), and the + * hash function for ECDSA signatures is always SHA-1 (id 2). + * + * - When using TLS 1.2, the list of hash functions is trimmed + * down to include only hash functions that the client context + * can support. The actual server list can be obtained with + * `br_ssl_client_get_server_hashes()`; that list may be used + * to select the certificate chain to send to the server. + * + * \param pctx certificate handler context. + * \param cc SSL client context. + * \param auth_types supported authentication types and algorithms. + * \param choices destination structure for the policy choices. + */ + void (*choose)(const br_ssl_client_certificate_class **pctx, + const br_ssl_client_context *cc, uint32_t auth_types, + br_ssl_client_certificate *choices); + + /** + * \brief Perform key exchange (client part). + * + * This callback is invoked in case of a full static ECDH key + * exchange: + * + * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; + * + * - the server requests a client certificate; + * + * - the client has, and sends, a client certificate that + * uses an EC key in the same curve as the server's key, + * and chooses static ECDH (the `hash_id` field in the choice + * structure was set to -1). + * + * In that situation, this callback is invoked to compute the + * client-side ECDH: the provided `data` (of length `*len` bytes) + * is the server's public key point (as decoded from its + * certificate), and the client shall multiply that point with + * its own private key, and write back the X coordinate of the + * resulting point in the same buffer, starting at offset 0. + * The `*len` value shall be modified to designate the actual + * length of the X coordinate. + * + * The callback must uphold the following: + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx certificate handler context. + * \param data server public key point. + * \param len public key point length / X coordinate length. + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (client authentication). + * + * This callback is invoked when a client certificate was sent, + * and static ECDH is not used. It shall compute a signature, + * using the client's private key, over the provided hash value + * (which is the hash of all previous handshake messages). + * + * On input, the hash value to sign is in `data`, of size + * `hv_len`; the involved hash function is identified by + * `hash_id`. The signature shall be computed and written + * back into `data`; the total size of that buffer is `len` + * bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * For RSA signatures, the `hash_id` may be 0, in which case + * this is the special header-less signature specified in TLS 1.0 + * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 + * v1.5 signatures shall be computed. + * + * For ECDSA signatures, the signature value shall use the ASN.1 + * based encoding. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx certificate handler context. + * \param hash_id hash function identifier. + * \param hv_len hash value length (in bytes). + * \param data input/output buffer (hash value, then signature). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len); +}; + +/** + * \brief A single-chain RSA client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_client_certificate_rsa_context; + +/** + * \brief A single-chain EC client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * This handler may support both static ECDH, and ECDSA signatures + * (either usage may be selectively disabled). + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_client_certificate_ec_context; + +/** + * \brief Context structure for a SSL client. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_client_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Minimum ClientHello length; padding with an extension (RFC + * 7685) is added if necessary to match at least that length. + * Such padding is nominally unnecessary, but it has been used + * to work around some server implementation bugs. + */ + uint16_t min_clienthello_len; + + /* + * Bit field for algoithms (hash + signature) supported by the + * server when requesting a client certificate. + */ + uint32_t hashes; + + /* + * Server's public key curve. + */ + int server_curve; + + /* + * Context for certificate handler. + */ + const br_ssl_client_certificate_class **client_auth_vtable; + + /* + * Client authentication type. + */ + unsigned char auth_type; + + /* + * Hash function to use for the client signature. This is 0xFF + * if static ECDH is used. + */ + unsigned char hash_id; + + /* + * For the core certificate handlers, thus avoiding (in most + * cases) the need for an externally provided policy context. + */ + union { + const br_ssl_client_certificate_class *vtable; + br_ssl_client_certificate_rsa_context single_rsa; + br_ssl_client_certificate_ec_context single_ec; + } client_auth; + + /* + * Implementations. + */ + br_rsa_public irsapub; +#endif +}; + +/** + * \brief Get the hash functions and signature algorithms supported by + * the server. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc client context. + * \return the server-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the server key curve. + * + * This function returns the ID for the curve used by the server's public + * key. This is set when the server's certificate chain is processed; + * this value is 0 if the server's key is not an EC key. + * + * \return the server's public key curve ID, or 0. + */ +static inline int +br_ssl_client_get_server_curve(const br_ssl_client_context *cc) +{ + return cc->server_curve; +} + +/* + * Each br_ssl_client_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full all supported versions and suites; constant-time implementations + * TODO: add other profiles + */ + +/** + * \brief SSL client profile: full. + * + * This function initialises the provided SSL client context with + * all supported algorithms and cipher suites. It also initialises + * a companion X.509 validation engine with all supported algorithms, + * and the provided trust anchors; the X.509 engine will be used by + * the client context to validate the server's certificate. + * + * \param cc client context to initialise. + * \param xc X.509 validation context to initialise. + * \param trust_anchors trust anchors to use. + * \param trust_anchors_num number of trust anchors. + */ +void br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Clear the complete contents of a SSL client context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc client context to clear. + */ +void br_ssl_client_zero(br_ssl_client_context *cc); + +/** + * \brief Set an externally provided client certificate handler context. + * + * The handler's methods are invoked when the server requests a client + * certificate. + * + * \param cc client context. + * \param pctx certificate handler context (pointer to its vtable field). + */ +static inline void +br_ssl_client_set_client_certificate(br_ssl_client_context *cc, + const br_ssl_client_certificate_class **pctx) +{ + cc->client_auth_vtable = pctx; +} + +/** + * \brief Set the RSA public-key operations implementation. + * + * This will be used to encrypt the pre-master secret with the server's + * RSA public key (RSA-encryption cipher suites only). + * + * \param cc client context. + * \param irsapub RSA public-key encryption implementation. + */ +static inline void +br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) +{ + cc->irsapub = irsapub; +} + +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + +/** + * \brief Set the minimum ClientHello length (RFC 7685 padding). + * + * If this value is set and the ClientHello would be shorter, then + * the Pad ClientHello extension will be added with enough padding bytes + * to reach the target size. Because of the extension header, the resulting + * size will sometimes be slightly more than `len` bytes if the target + * size cannot be exactly met. + * + * The target length relates to the _contents_ of the ClientHello, not + * counting its 4-byte header. For instance, if `len` is set to 512, + * then the padding will bring the ClientHello size to 516 bytes with its + * header, and 521 bytes when counting the 5-byte record header. + * + * \param cc client context. + * \param len minimum ClientHello length (in bytes). + */ +static inline void +br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) +{ + cc->min_clienthello_len = len; +} + +/** + * \brief Prepare or reset a client context for a new connection. + * + * The `server_name` parameter is used to fill the SNI extension; the + * X.509 "minimal" engine will also match that name against the server + * names included in the server's certificate. If the parameter is + * `NULL` then no SNI extension will be sent, and the X.509 "minimal" + * engine (if used for server certificate validation) will not check + * presence of any specific name in the received certificate. + * + * Therefore, setting the `server_name` to `NULL` shall be reserved + * to cases where alternate or additional methods are used to ascertain + * that the right server public key is used (e.g. a "known key" model). + * + * If `resume_session` is non-zero and the context was previously used + * then the session parameters may be reused (depending on whether the + * server previously sent a non-empty session ID, and accepts the session + * resumption). The session parameters for session resumption can also + * be set explicitly with `br_ssl_engine_set_session_parameters()`. + * + * On failure, the context is marked as failed, and this function + * returns 0. A possible failure condition is when no initial entropy + * was injected, and none could be obtained from the OS (either OS + * randomness gathering is not supported, or it failed). + * + * \param cc client context. + * \param server_name target server name, or `NULL`. + * \param resume_session non-zero to try session resumption. + * \return 0 on failure, 1 on success. + */ +int br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session); + +/** + * \brief Forget any session in the context. + * + * This means that the next handshake that uses this context will + * necessarily be a full handshake (this applies both to new connections + * and to renegotiations). + * + * \param cc client context. + */ +static inline void +br_ssl_client_forget_session(br_ssl_client_context *cc) +{ + cc->eng.session.session_id_len = 0; +} + +/** + * \brief Set client certificate chain and key (single RSA case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an RSA public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * \param cc SSL client context. + * \param chain client certificate chain (SSL order: EE comes first). + * \param chain_len client chain length (number of certificates). + * \param sk client private key. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); + +/* + * \brief Set the client certificate chain and key (single EC case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an EC public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` + * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value + * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA + * signature implementation must be provided; otherwise, the `iecdsa` + * parameter may be 0. + * + * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or + * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA + * that issued (signed) the client certificate. That value is used with + * full static ECDH: support of the certificate by the server depends + * on how the certificate was signed. (Note: when using TLS 1.2, this + * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Type for a "translated cipher suite", as an array of two + * 16-bit integers. + * + * The first element is the cipher suite identifier (as used on the wire). + * The second element is the concatenation of four 4-bit elements which + * characterise the cipher suite contents. In most to least significant + * order, these 4-bit elements are: + * + * - Bits 12 to 15: key exchange + server key type + * + * | val | symbolic constant | suite type | details | + * | :-- | :----------------------- | :---------- | :----------------------------------------------- | + * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | + * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | + * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | + * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | + * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | + * + * - Bits 8 to 11: symmetric encryption algorithm + * + * | val | symbolic constant | symmetric encryption | key strength (bits) | + * | :-- | :--------------------- | :------------------- | :------------------ | + * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | + * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | + * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | + * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | + * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | + * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | + * + * - Bits 4 to 7: MAC algorithm + * + * | val | symbolic constant | MAC type | details | + * | :-- | :----------------- | :----------- | :------------------------------------ | + * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | + * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | + * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | + * + * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 + * + * | val | symbolic constant | hash function | details | + * | :-- | :----------------- | :------------ | :----------------------------------- | + * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | + * + * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has + * standard identifier 0x009C, and is translated to 0x0304, for, in + * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), + * SHA-256 in the TLS PRF (4). + */ +typedef uint16_t br_suite_translated[2]; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Constants are already documented in the br_suite_translated type. + */ + +#define BR_SSLKEYX_RSA 0 +#define BR_SSLKEYX_ECDHE_RSA 1 +#define BR_SSLKEYX_ECDHE_ECDSA 2 +#define BR_SSLKEYX_ECDH_RSA 3 +#define BR_SSLKEYX_ECDH_ECDSA 4 + +#define BR_SSLENC_3DES_CBC 0 +#define BR_SSLENC_AES128_CBC 1 +#define BR_SSLENC_AES256_CBC 2 +#define BR_SSLENC_AES128_GCM 3 +#define BR_SSLENC_AES256_GCM 4 +#define BR_SSLENC_CHACHA20 5 + +#define BR_SSLMAC_AEAD 0 +#define BR_SSLMAC_SHA1 br_sha1_ID +#define BR_SSLMAC_SHA256 br_sha256_ID +#define BR_SSLMAC_SHA384 br_sha384_ID + +#define BR_SSLPRF_SHA256 br_sha256_ID +#define BR_SSLPRF_SHA384 br_sha384_ID + +#endif + +/* + * Pre-declaration for the SSL server context. + */ +typedef struct br_ssl_server_context_ br_ssl_server_context; + +/** + * \brief Type for the server policy choices, taken after analysis of + * the client message (ClientHello). + */ +typedef struct { + /** + * \brief Cipher suite to use with that client. + */ + uint16_t cipher_suite; + + /** + * \brief Hash function or algorithm for signing the ServerKeyExchange. + * + * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` + * cipher suites; it is used only for `TLS_ECDHE_*` suites, in + * which the server _signs_ the ephemeral EC Diffie-Hellman + * parameters sent to the client. + * + * This identifier must be one of the following values: + * + * - `0xFF00 + id`, where `id` is a hash function identifier + * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); + * + * - a full 16-bit identifier, lower than `0xFF00`. + * + * If the first option is used, then the SSL engine will + * compute the hash of the data that is to be signed, with the + * designated hash function. The `do_sign()` method will be + * invoked with that hash value provided in the the `data` + * buffer. + * + * If the second option is used, then the SSL engine will NOT + * compute a hash on the data; instead, it will provide the + * to-be-signed data itself in `data`, i.e. the concatenation of + * the client random, server random, and encoded ECDH + * parameters. Furthermore, with TLS-1.2 and later, the 16-bit + * identifier will be used "as is" in the protocol, in the + * SignatureAndHashAlgorithm; for instance, `0x0401` stands for + * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash + * function (the `04`). + * + * Take care that with TLS 1.0 and 1.1, the hash function is + * constrainted by the protocol: RSA signature must use + * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 + * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a + * SignatureAndHashAlgorithm field in their ServerKeyExchange + * messages, any value below `0xFF00` will be usable to send the + * raw ServerKeyExchange data to the `do_sign()` callback, but + * that callback must still follow the protocol requirements + * when generating the signature. + */ + unsigned algo_id; + + /** + * \brief Certificate chain to send to the client. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The server + * code does not try to decode these elements. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + */ + size_t chain_len; + +} br_ssl_server_choices; + +/** + * \brief Class type for a policy handler (server side). + * + * A policy handler selects the policy parameters for a connection + * (cipher suite and other algorithms, and certificate chain to send to + * the client); it also performs the server-side computations involving + * its permanent private key. + * + * The SSL server engine will invoke first `choose()`, once the + * ClientHello message has been received, then either `do_keyx()` + * `do_sign()`, depending on the cipher suite. + */ +typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; +struct br_ssl_server_policy_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Select algorithms and certificates for this connection. + * + * This callback function shall fill the provided `choices` + * structure with the policy choices for this connection. This + * entails selecting the cipher suite, hash function for signing + * the ServerKeyExchange (applicable only to ECDHE cipher suites), + * and certificate chain to send. + * + * The callback receives a pointer to the server context that + * contains the relevant data. In particular, the functions + * `br_ssl_server_get_client_suites()`, + * `br_ssl_server_get_client_hashes()` and + * `br_ssl_server_get_client_curves()` can be used to obtain + * the cipher suites, hash functions and elliptic curves + * supported by both the client and server, respectively. The + * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` + * functions yield the protocol version and requested server name + * (SNI), respectively. + * + * This function may modify its context structure (`pctx`) in + * arbitrary ways to keep track of its own choices. + * + * This function shall return 1 if appropriate policy choices + * could be made, or 0 if this connection cannot be pursued. + * + * \param pctx policy context. + * \param cc SSL server context. + * \param choices destination structure for the policy choices. + * \return 1 on success, 0 on error. + */ + int (*choose)(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices); + + /** + * \brief Perform key exchange (server part). + * + * This callback is invoked to perform the server-side cryptographic + * operation for a key exchange that is not ECDHE. This callback + * uses the private key. + * + * **For RSA key exchange**, the provided `data` (of length `*len` + * bytes) shall be decrypted with the server's private key, and + * the 48-byte premaster secret copied back to the first 48 bytes + * of `data`. + * + * - The caller makes sure that `*len` is at least 59 bytes. + * + * - This callback MUST check that the provided length matches + * that of the key modulus; it shall report an error otherwise. + * + * - If the length matches that of the RSA key modulus, then + * processing MUST be constant-time, even if decryption fails, + * or the padding is incorrect, or the plaintext message length + * is not exactly 48 bytes. + * + * - This callback needs not check the two first bytes of the + * obtained pre-master secret (the caller will do that). + * + * - If an error is reported (0), then what the callback put + * in the first 48 bytes of `data` is unimportant (the caller + * will use random bytes instead). + * + * **For ECDH key exchange**, the provided `data` (of length `*len` + * bytes) is the elliptic curve point from the client. The + * callback shall multiply it with its private key, and store + * the resulting X coordinate in `data`, starting at offset 0, + * and set `*len` to the length of the X coordinate. + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx policy context. + * \param data key exchange data from the client. + * \param len key exchange data length (in bytes). + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (for a ServerKeyExchange message). + * + * This callback function is invoked for ECDHE cipher suites. On + * input, the hash value or message to sign is in `data`, of + * size `hv_len`; the involved hash function or algorithm is + * identified by `algo_id`. The signature shall be computed and + * written back into `data`; the total size of that buffer is + * `len` bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * The `algo_id` value matches that which was written in the + * `choices` structures by the `choose()` callback. This will be + * one of the following: + * + * - `0xFF00 + id` for a hash function identifier `id`. In + * that case, the `data` buffer contains a hash value + * already computed over the data that is to be signed, + * of length `hv_len`. The `id` may be 0 to designate the + * special MD5+SHA-1 concatenation (old-style RSA signing). + * + * - Another value, lower than `0xFF00`. The `data` buffer + * then contains the raw, non-hashed data to be signed + * (concatenation of the client and server randoms and + * ECDH parameters). The callback is responsible to apply + * any relevant hashing as part of the signing process. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx policy context. + * \param algo_id hash function / algorithm identifier. + * \param data input/output buffer (message/hash, then signature). + * \param hv_len hash value or message length (in bytes). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_server_policy_class **pctx, + unsigned algo_id, + unsigned char *data, size_t hv_len, size_t len); +}; + +/** + * \brief A single-chain RSA policy handler. + * + * This policy context uses a single certificate chain, and a RSA + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + unsigned allowed_usages; + br_rsa_private irsacore; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_server_policy_rsa_context; + +/** + * \brief A single-chain EC policy handler. + * + * This policy context uses a single certificate chain, and an EC + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Due to how TLS is defined, this context must be made aware whether + * the server certificate was itself signed with RSA or ECDSA. The code + * does not try to decode the certificate to obtain that information. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned cert_issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_server_policy_ec_context; + +/** + * \brief Class type for a session parameter cache. + * + * Session parameters are saved in the cache with `save()`, and + * retrieved with `load()`. The cache implementation can apply any + * storage and eviction strategy that it sees fit. The SSL server + * context that performs the request is provided, so that its + * functionalities may be used by the implementation (e.g. hash + * functions or random number generation). + */ +typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; +struct br_ssl_session_cache_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Record a session. + * + * This callback should record the provided session parameters. + * The `params` structure is transient, so its contents shall + * be copied into the cache. The session ID has been randomly + * generated and always has length exactly 32 bytes. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params session parameters to save. + */ + void (*save)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params); + + /** + * \brief Lookup a session in the cache. + * + * The session ID to lookup is in `params` and always has length + * exactly 32 bytes. If the session parameters are found in the + * cache, then the parameters shall be copied into the `params` + * structure. Returned value is 1 on successful lookup, 0 + * otherwise. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params destination for session parameters. + * \return 1 if found, 0 otherwise. + */ + int (*load)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params); +}; + +/** + * \brief Context for a basic cache system. + * + * The system stores session parameters in a buffer provided at + * initialisation time. Each entry uses exactly 100 bytes, and + * buffer sizes up to 4294967295 bytes are supported. + * + * Entries are evicted with a LRU (Least Recently Used) policy. A + * search tree is maintained to keep lookups fast even with large + * caches. + * + * Apart from the first field (vtable pointer), the structure + * contents are opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_session_cache_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char *store; + size_t store_len, store_ptr; + unsigned char index_key[32]; + const br_hash_class *hash; + int init_done; + uint32_t head, tail, root; +#endif +} br_ssl_session_cache_lru; + +/** + * \brief Initialise a LRU session cache with the provided storage space. + * + * The provided storage space must remain valid as long as the cache + * is used. Arbitrary lengths are supported, up to 4294967295 bytes; + * each entry uses up exactly 100 bytes. + * + * \param cc session cache context. + * \param store storage space for cached entries. + * \param store_len storage space length (in bytes). + */ +void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len); + +/** + * \brief Forget an entry in an LRU session cache. + * + * The session cache context must have been initialised. The entry + * with the provided session ID (of exactly 32 bytes) is looked for + * in the cache; if located, it is disabled. + * + * \param cc session cache context. + * \param id session ID to forget. + */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id); + +/** + * \brief Context structure for a SSL server. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_server_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Maximum version from the client. + */ + uint16_t client_max_version; + + /* + * Session cache. + */ + const br_ssl_session_cache_class **cache_vtable; + + /* + * Translated cipher suites supported by the client. The list + * is trimmed to include only the cipher suites that the + * server also supports; they are in the same order as in the + * client message. + */ + br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; + unsigned char client_suites_num; + + /* + * Hash functions supported by the client, with ECDSA and RSA + * (bit mask). For hash function with id 'x', set bit index is + * x for RSA, x+8 for ECDSA. For newer algorithms, with ID + * 0x08**, bit 16+k is set for algorithm 0x0800+k. + */ + uint32_t hashes; + + /* + * Curves supported by the client (bit mask, for named curves). + */ + uint32_t curves; + + /* + * Context for chain handler. + */ + const br_ssl_server_policy_class **policy_vtable; + uint16_t sign_hash_id; + + /* + * For the core handlers, thus avoiding (in most cases) the + * need for an externally provided policy context. + */ + union { + const br_ssl_server_policy_class *vtable; + br_ssl_server_policy_rsa_context single_rsa; + br_ssl_server_policy_ec_context single_ec; + } chain_handler; + + /* + * Buffer for the ECDHE private key. + */ + unsigned char ecdhe_key[70]; + size_t ecdhe_key_len; + + /* + * Trust anchor names for client authentication. "ta_names" and + * "tas" cannot be both non-NULL. + */ + const br_x500_name *ta_names; + const br_x509_trust_anchor *tas; + size_t num_tas; + size_t cur_dn_index; + const unsigned char *cur_dn; + size_t cur_dn_len; + + /* + * Buffer for the hash value computed over all handshake messages + * prior to CertificateVerify, and identifier for the hash function. + */ + unsigned char hash_CV[64]; + size_t hash_CV_len; + int hash_CV_id; + + /* + * Server-specific implementations. + * (none for now) + */ +#endif +}; + +/* + * Each br_ssl_server_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full_rsa all supported algorithm, server key type is RSA + * full_ec all supported algorithm, server key type is EC + * TODO: add other profiles + * + * Naming scheme for "minimal" profiles: min123 + * + * -- character 1: key exchange + * r = RSA + * e = ECDHE_RSA + * f = ECDHE_ECDSA + * u = ECDH_RSA + * v = ECDH_ECDSA + * -- character 2: version / PRF + * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 + * 2 = TLS 1.2 with SHA-256 + * 3 = TLS 1.2 with SHA-384 + * -- character 3: encryption + * a = AES/CBC + * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 + */ + +/** + * \brief SSL server profile: full_rsa. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on a RSA + * key pair. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: full_ec. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on an EC + * key pair. + * + * The key type of the CA that issued the server's certificate must + * be provided, since it matters for ECDH cipher suites (ECDH_RSA + * suites require a RSA-powered CA). The key type is either + * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len chain length (number of certificates). + * \param cert_issuer_key_type certificate issuer's key type. + * \param sk EC private key. + */ +void br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minr2g. + * + * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is + * RSA, and RSA key exchange is used (not forward secure, but uses little + * CPU in the client). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: mine2g. + * + * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key + * is RSA, and ECDHE key exchange is used. This suite provides forward + * security, with a higher CPU expense on the client, and a somewhat + * larger code footprint (compared to "minr2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2g. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security, with a higher CPU expense on the client and server + * (by a factor of about 3 to 4), and a somewhat larger code footprint + * (compared to "minu2g" and "minv2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minu2g. + * + * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * a RSA key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minv2g. + * + * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * an EC key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: mine2c. + * + * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is RSA, and ECDHE key exchange is used. This suite + * provides forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2c. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief Get the supported client suites. + * + * This function shall be called only after the ClientHello has been + * processed, typically from the policy engine. The returned array + * contains the cipher suites that are supported by both the client + * and the server; these suites are in client preference order, unless + * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case + * they are in server preference order. + * + * The suites are _translated_, which means that each suite is given + * as two 16-bit integers: the standard suite identifier, and its + * translated version, broken down into its individual components, + * as explained with the `br_suite_translated` type. + * + * The returned array is allocated in the context and will be rewritten + * by each handshake. + * + * \param cc server context. + * \param num receives the array size (number of suites). + * \return the translated common cipher suites, in preference order. + */ +static inline const br_suite_translated * +br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) +{ + *num = cc->client_suites_num; + return cc->client_suites; +} + +/** + * \brief Get the hash functions and signature algorithms supported by + * the client. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc server context. + * \return the client-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the elliptic curves supported by the client. + * + * This is a bit field (bit x is set if curve of ID x is supported). + * + * \param cc server context. + * \return the client-supported elliptic curves. + */ +static inline uint32_t +br_ssl_server_get_client_curves(const br_ssl_server_context *cc) +{ + return cc->curves; +} + +/** + * \brief Clear the complete contents of a SSL server context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc server context to clear. + */ +void br_ssl_server_zero(br_ssl_server_context *cc); + +/** + * \brief Set an externally provided policy context. + * + * The policy context's methods are invoked to decide the cipher suite + * and certificate chain, and to perform operations involving the server's + * private key. + * + * \param cc server context. + * \param pctx policy context (pointer to its vtable field). + */ +static inline void +br_ssl_server_set_policy(br_ssl_server_context *cc, + const br_ssl_server_policy_class **pctx) +{ + cc->policy_vtable = pctx; +} + +/** + * \brief Set the server certificate chain and key (single RSA case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with a RSA + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for + * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). + * + * \param cc server context. + * \param chain server certificate chain to send to the client. + * \param chain_len chain length (number of certificates). + * \param sk server private key (RSA). + * \param allowed_usages allowed private key usages. + * \param irsacore RSA core implementation. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); + +/** + * \brief Set the server certificate chain and key (single EC case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with an EC + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for + * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). + * + * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), + * the algorithm type of the key used by the issuing CA to sign the + * server's certificate must be provided, as `cert_issuer_key_type` + * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_server_set_single_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Activate client certificate authentication. + * + * The trust anchor encoded X.500 names (DN) to send to the client are + * provided. A client certificate will be requested and validated through + * the X.509 validator configured in the SSL engine. If `num` is 0, then + * client certificate authentication is disabled. + * + * If the client does not send a certificate, or on validation failure, + * the handshake aborts. Unauthenticated clients can be tolerated by + * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param ta_names encoded trust anchor names. + * \param num number of encoded trust anchor names. + */ +static inline void +br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, + const br_x500_name *ta_names, size_t num) +{ + cc->ta_names = ta_names; + cc->tas = NULL; + cc->num_tas = num; +} + +/** + * \brief Activate client certificate authentication. + * + * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the + * trust anchor names are provided not as an array of stand-alone names + * (`br_x500_name` structures), but as an array of trust anchors + * (`br_x509_trust_anchor` structures). The server engine itself will + * only use the `dn` field of each trust anchor. This is meant to allow + * defining a single array of trust anchors, to be used here and in the + * X.509 validation engine itself. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param tas trust anchors (only names are used). + * \param num number of trust anchors. + */ +static inline void +br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, + const br_x509_trust_anchor *tas, size_t num) +{ + cc->ta_names = NULL; + cc->tas = tas; + cc->num_tas = num; +} + +/** + * \brief Configure the cache for session parameters. + * + * The cache context is provided as a pointer to its first field (vtable + * pointer). + * + * \param cc server context. + * \param vtable session cache context. + */ +static inline void +br_ssl_server_set_cache(br_ssl_server_context *cc, + const br_ssl_session_cache_class **vtable) +{ + cc->cache_vtable = vtable; +} + +/** + * \brief Prepare or reset a server context for handling an incoming client. + * + * \param cc server context. + * \return 1 on success, 0 on error. + */ +int br_ssl_server_reset(br_ssl_server_context *cc); + +/* ===================================================================== */ + +/* + * Context for the simplified I/O context. The transport medium is accessed + * through the low_read() and low_write() callback functions, each with + * its own opaque context pointer. + * + * low_read() read some bytes, at most 'len' bytes, into data[]. The + * returned value is the number of read bytes, or -1 on error. + * The 'len' parameter is guaranteed never to exceed 20000, + * so the length always fits in an 'int' on all platforms. + * + * low_write() write up to 'len' bytes, to be read from data[]. The + * returned value is the number of written bytes, or -1 on + * error. The 'len' parameter is guaranteed never to exceed + * 20000, so the length always fits in an 'int' on all + * parameters. + * + * A socket closure (if the transport medium is a socket) should be reported + * as an error (-1). The callbacks shall endeavour to block until at least + * one byte can be read or written; a callback returning 0 at times is + * acceptable, but this normally leads to the callback being immediately + * called again, so the callback should at least always try to block for + * some time if no I/O can take place. + * + * The SSL engine naturally applies some buffering, so the callbacks need + * not apply buffers of their own. + */ +/** + * \brief Context structure for the simplified SSL I/O wrapper. + * + * This structure is initialised with `br_sslio_init()`. Its contents + * are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_ssl_engine_context *engine; + int (*low_read)(void *read_context, + unsigned char *data, size_t len); + void *read_context; + int (*low_write)(void *write_context, + const unsigned char *data, size_t len); + void *write_context; +#endif +} br_sslio_context; + +/** + * \brief Initialise a simplified I/O wrapper context. + * + * The simplified I/O wrapper offers a simpler read/write API for a SSL + * engine (client or server), using the provided callback functions for + * reading data from, or writing data to, the transport medium. + * + * The callback functions have the following semantics: + * + * - Each callback receives an opaque context value (of type `void *`) + * that the callback may use arbitrarily (or possibly ignore). + * + * - `low_read()` reads at least one byte, at most `len` bytes, from + * the transport medium. Read bytes shall be written in `data`. + * + * - `low_write()` writes at least one byte, at most `len` bytes, unto + * the transport medium. The bytes to write are read from `data`. + * + * - The `len` parameter is never zero, and is always lower than 20000. + * + * - The number of processed bytes (read or written) is returned. Since + * that number is less than 20000, it always fits on an `int`. + * + * - On error, the callbacks return -1. Reaching end-of-stream is an + * error. Errors are permanent: the SSL connection is terminated. + * + * - Callbacks SHOULD NOT return 0. This is tolerated, as long as + * callbacks endeavour to block for some non-negligible amount of + * time until at least one byte can be sent or received (if a + * callback returns 0, then the wrapper invokes it again + * immediately). + * + * - Callbacks MAY return as soon as at least one byte is processed; + * they MAY also insist on reading or writing _all_ requested bytes. + * Since SSL is a self-terminated protocol (each record has a length + * header), this does not change semantics. + * + * - Callbacks need not apply any buffering (for performance) since SSL + * itself uses buffers. + * + * \param ctx wrapper context to initialise. + * \param engine SSL engine to wrap. + * \param low_read callback for reading data from the transport. + * \param read_context context pointer for `low_read()`. + * \param low_write callback for writing data on the transport. + * \param write_context context pointer for `low_write()`. + */ +void br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context); + +/** + * \brief Read some application data from a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been obtained. + * Returned value is the number of bytes read, or -1 on error. The + * number of bytes always fits on an 'int' (data from a single SSL/TLS + * record is returned). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len maximum number of bytes to obtain. + * \return number of bytes obtained, or -1 on error. + */ +int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Read application data from a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes are read, + * or an error is reached. Returned value is 0 on success, -1 on error. + * A normal (verified) SSL closure before that many bytes are obtained + * is reported as an error by this function. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len number of bytes to obtain. + * \return 0 on success, or -1 on error. + */ +int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Write some application data unto a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been written. + * Returned value is the number of bytes written, or -1 on error. The + * number of bytes always fits on an 'int' (less than 20000). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len maximum number of bytes to write. + * \return number of bytes written, or -1 on error. + */ +int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Write application data unto a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes have been + * written, or an error is reached. Returned value is 0 on success, -1 + * on error. A normal (verified) SSL closure before that many bytes are + * written is reported as an error by this function. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len number of bytes to write. + * \return 0 on success, or -1 on error. + */ +int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Flush pending data. + * + * This call makes sure that any buffered application data in the + * provided context (including the wrapped SSL engine) has been sent + * to the transport medium (i.e. accepted by the `low_write()` callback + * method). If there is no such pending data, then this function does + * nothing (and returns a success, i.e. 0). + * + * If the underlying transport medium has its own buffers, then it is + * up to the caller to ensure the corresponding flushing. + * + * Returned value is 0 on success, -1 on error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_flush(br_sslio_context *cc); + +/** + * \brief Close the SSL connection. + * + * This call runs the SSL closure protocol (sending a `close_notify`, + * receiving the response `close_notify`). When it returns, the SSL + * connection is finished. It is still up to the caller to manage the + * possible transport-level termination, if applicable (alternatively, + * the underlying transport stream may be reused for non-SSL messages). + * + * Returned value is 0 on success, -1 on error. A failure by the peer + * to process the complete closure protocol (i.e. sending back the + * `close_notify`) is an error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_close(br_sslio_context *cc); + +/* ===================================================================== */ + +/* + * Symbolic constants for cipher suites. + */ + +/* From RFC 5246 */ +#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 +#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 +#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 +#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B +#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 +#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 +#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D +#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 +#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 +#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B +#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 +#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D + +/* From RFC 4492 */ +#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 +#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 +#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 +#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 +#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 +#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B +#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C +#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F +#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 +#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 +#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 +#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 +#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 + +/* From RFC 5288 */ +#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F +#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 +#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 +#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 +#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 +#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 +#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 +#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 +#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 + +/* From RFC 5289 */ +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E +#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 +#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 + +/* From RFC 6655 and 7251 */ +#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C +#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D +#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 +#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF + +/* From RFC 7905 */ +#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 +#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 +#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA +#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB +#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC +#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD +#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE + +/* From RFC 7507 */ +#define BR_TLS_FALLBACK_SCSV 0x5600 + +/* + * Symbolic constants for alerts. + */ +#define BR_ALERT_CLOSE_NOTIFY 0 +#define BR_ALERT_UNEXPECTED_MESSAGE 10 +#define BR_ALERT_BAD_RECORD_MAC 20 +#define BR_ALERT_RECORD_OVERFLOW 22 +#define BR_ALERT_DECOMPRESSION_FAILURE 30 +#define BR_ALERT_HANDSHAKE_FAILURE 40 +#define BR_ALERT_BAD_CERTIFICATE 42 +#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define BR_ALERT_CERTIFICATE_REVOKED 44 +#define BR_ALERT_CERTIFICATE_EXPIRED 45 +#define BR_ALERT_CERTIFICATE_UNKNOWN 46 +#define BR_ALERT_ILLEGAL_PARAMETER 47 +#define BR_ALERT_UNKNOWN_CA 48 +#define BR_ALERT_ACCESS_DENIED 49 +#define BR_ALERT_DECODE_ERROR 50 +#define BR_ALERT_DECRYPT_ERROR 51 +#define BR_ALERT_PROTOCOL_VERSION 70 +#define BR_ALERT_INSUFFICIENT_SECURITY 71 +#define BR_ALERT_INTERNAL_ERROR 80 +#define BR_ALERT_USER_CANCELED 90 +#define BR_ALERT_NO_RENEGOTIATION 100 +#define BR_ALERT_UNSUPPORTED_EXTENSION 110 +#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bearssl_x509.h b/template/sysroot/include/bearssl_x509.h new file mode 100644 index 0000000..7668e1d --- /dev/null +++ b/template/sysroot/include/bearssl_x509.h @@ -0,0 +1,1474 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_X509_H__ +#define BR_BEARSSL_X509_H__ + +#include +#include + +#include "bearssl_ec.h" +#include "bearssl_hash.h" +#include "bearssl_rsa.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_x509.h + * + * # X.509 Certificate Chain Processing + * + * An X.509 processing engine receives an X.509 chain, chunk by chunk, + * as received from a SSL/TLS client or server (the client receives the + * server's certificate chain, and the server receives the client's + * certificate chain if it requested a client certificate). The chain + * is thus injected in the engine in SSL order (end-entity first). + * + * The engine's job is to return the public key to use for SSL/TLS. + * How exactly that key is obtained and verified is entirely up to the + * engine. + * + * **The "known key" engine** returns a public key which is already known + * from out-of-band information (e.g. the client _remembers_ the key from + * a previous connection, as in the usual SSH model). This is the simplest + * engine since it simply ignores the chain, thereby avoiding the need + * for any decoding logic. + * + * **The "minimal" engine** implements minimal X.509 decoding and chain + * validation: + * + * - The provided chain should validate "as is". There is no attempt + * at reordering, skipping or downloading extra certificates. + * + * - X.509 v1, v2 and v3 certificates are supported. + * + * - Trust anchors are a DN and a public key. Each anchor is either a + * "CA" anchor, or a non-CA. + * + * - If the end-entity certificate matches a non-CA anchor (subject DN + * is equal to the non-CA name, and public key is also identical to + * the anchor key), then this is a _direct trust_ case and the + * remaining certificates are ignored. + * + * - Unless direct trust is applied, the chain must be verifiable up to + * a certificate whose issuer DN matches the DN from a "CA" trust anchor, + * and whose signature is verifiable against that anchor's public key. + * Subsequent certificates in the chain are ignored. + * + * - The engine verifies subject/issuer DN matching, and enforces + * processing of Basic Constraints and Key Usage extensions. The + * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name, + * Subject Directory Attribute, CRL Distribution Points, Freshest CRL, + * Authority Info Access and Subject Info Access extensions are + * ignored. The Subject Alt Name is decoded for the end-entity + * certificate under some conditions (see below). Other extensions + * are ignored if non-critical, or imply chain rejection if critical. + * + * - The Subject Alt Name extension is parsed for names of type `dNSName` + * when decoding the end-entity certificate, and only if there is a + * server name to match. If there is no SAN extension, then the + * Common Name from the subjectDN is used. That name matching is + * case-insensitive and honours a single starting wildcard (i.e. if + * the name in the certificate starts with "`*.`" then this matches + * any word as first element). Note: this name matching is performed + * also in the "direct trust" model. + * + * - DN matching is byte-to-byte equality (a future version might + * include some limited processing for case-insensitive matching and + * whitespace normalisation). + * + * - Successful validation produces a public key type but also a set + * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * The caller is responsible for checking that the key type and + * usages are compatible with the expected values (e.g. with the + * selected cipher suite, when the client validates the server's + * certificate). + * + * **Important caveats:** + * + * - The "minimal" engine does not check revocation status. The relevant + * extensions are ignored, and CRL or OCSP responses are not gathered + * or checked. + * + * - The "minimal" engine does not currently support Name Constraints + * (some basic functionality to handle sub-domains may be added in a + * later version). + * + * - The decoder is not "validating" in the sense that it won't reject + * some certificates with invalid field values when these fields are + * not actually processed. + */ + +/* + * X.509 error codes are in the 32..63 range. + */ + +/** \brief X.509 status: validation was successful; this is not actually + an error. */ +#define BR_ERR_X509_OK 32 + +/** \brief X.509 status: invalid value in an ASN.1 structure. */ +#define BR_ERR_X509_INVALID_VALUE 33 + +/** \brief X.509 status: truncated certificate. */ +#define BR_ERR_X509_TRUNCATED 34 + +/** \brief X.509 status: empty certificate chain (no certificate at all). */ +#define BR_ERR_X509_EMPTY_CHAIN 35 + +/** \brief X.509 status: decoding error: inner element extends beyond + outer element size. */ +#define BR_ERR_X509_INNER_TRUNC 36 + +/** \brief X.509 status: decoding error: unsupported tag class (application + or private). */ +#define BR_ERR_X509_BAD_TAG_CLASS 37 + +/** \brief X.509 status: decoding error: unsupported tag value. */ +#define BR_ERR_X509_BAD_TAG_VALUE 38 + +/** \brief X.509 status: decoding error: indefinite length. */ +#define BR_ERR_X509_INDEFINITE_LENGTH 39 + +/** \brief X.509 status: decoding error: extraneous element. */ +#define BR_ERR_X509_EXTRA_ELEMENT 40 + +/** \brief X.509 status: decoding error: unexpected element. */ +#define BR_ERR_X509_UNEXPECTED 41 + +/** \brief X.509 status: decoding error: expected constructed element, but + is primitive. */ +#define BR_ERR_X509_NOT_CONSTRUCTED 42 + +/** \brief X.509 status: decoding error: expected primitive element, but + is constructed. */ +#define BR_ERR_X509_NOT_PRIMITIVE 43 + +/** \brief X.509 status: decoding error: BIT STRING length is not multiple + of 8. */ +#define BR_ERR_X509_PARTIAL_BYTE 44 + +/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */ +#define BR_ERR_X509_BAD_BOOLEAN 45 + +/** \brief X.509 status: decoding error: value is off-limits. */ +#define BR_ERR_X509_OVERFLOW 46 + +/** \brief X.509 status: invalid distinguished name. */ +#define BR_ERR_X509_BAD_DN 47 + +/** \brief X.509 status: invalid date/time representation. */ +#define BR_ERR_X509_BAD_TIME 48 + +/** \brief X.509 status: certificate contains unsupported features that + cannot be ignored. */ +#define BR_ERR_X509_UNSUPPORTED 49 + +/** \brief X.509 status: key or signature size exceeds internal limits. */ +#define BR_ERR_X509_LIMIT_EXCEEDED 50 + +/** \brief X.509 status: key type does not match that which was expected. */ +#define BR_ERR_X509_WRONG_KEY_TYPE 51 + +/** \brief X.509 status: signature is invalid. */ +#define BR_ERR_X509_BAD_SIGNATURE 52 + +/** \brief X.509 status: validation time is unknown. */ +#define BR_ERR_X509_TIME_UNKNOWN 53 + +/** \brief X.509 status: certificate is expired or not yet valid. */ +#define BR_ERR_X509_EXPIRED 54 + +/** \brief X.509 status: issuer/subject DN mismatch in the chain. */ +#define BR_ERR_X509_DN_MISMATCH 55 + +/** \brief X.509 status: expected server name was not found in the chain. */ +#define BR_ERR_X509_BAD_SERVER_NAME 56 + +/** \brief X.509 status: unknown critical extension in certificate. */ +#define BR_ERR_X509_CRITICAL_EXTENSION 57 + +/** \brief X.509 status: not a CA, or path length constraint violation */ +#define BR_ERR_X509_NOT_CA 58 + +/** \brief X.509 status: Key Usage extension prohibits intended usage. */ +#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59 + +/** \brief X.509 status: public key found in certificate is too small. */ +#define BR_ERR_X509_WEAK_PUBLIC_KEY 60 + +/** \brief X.509 status: chain could not be linked to a trust anchor. */ +#define BR_ERR_X509_NOT_TRUSTED 62 + +/** + * \brief Aggregate structure for public keys. + */ +typedef struct { + /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */ + unsigned char key_type; + /** \brief Actual public key. */ + union { + /** \brief RSA public key. */ + br_rsa_public_key rsa; + /** \brief EC public key. */ + br_ec_public_key ec; + } key; +} br_x509_pkey; + +/** + * \brief Distinguished Name (X.500) structure. + * + * The DN is DER-encoded. + */ +typedef struct { + /** \brief Encoded DN data. */ + unsigned char *data; + /** \brief Encoded DN length (in bytes). */ + size_t len; +} br_x500_name; + +/** + * \brief Trust anchor structure. + */ +typedef struct { + /** \brief Encoded DN (X.500 name). */ + br_x500_name dn; + /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */ + unsigned flags; + /** \brief Anchor public key. */ + br_x509_pkey pkey; +} br_x509_trust_anchor; + +/** + * \brief Trust anchor flag: CA. + * + * A "CA" anchor is deemed fit to verify signatures on certificates. + * A "non-CA" anchor is accepted only for direct trust (server's + * certificate name and key match the anchor). + */ +#define BR_X509_TA_CA 0x0001 + +/* + * Key type: combination of a basic key type (low 4 bits) and some + * optional flags. + * + * For a public key, the basic key type only is set. + * + * For an expected key type, the flags indicate the intended purpose(s) + * for the key; the basic key type may be set to 0 to indicate that any + * key type compatible with the indicated purpose is acceptable. + */ +/** \brief Key type: algorithm is RSA. */ +#define BR_KEYTYPE_RSA 1 +/** \brief Key type: algorithm is EC. */ +#define BR_KEYTYPE_EC 2 + +/** + * \brief Key type: usage is "key exchange". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher + * suites). + */ +#define BR_KEYTYPE_KEYX 0x10 + +/** + * \brief Key type: usage is "signature". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites). + */ +#define BR_KEYTYPE_SIGN 0x20 + +/* + * start_chain Called when a new chain is started. If 'server_name' + * is not NULL and non-empty, then it is a name that + * should be looked for in the EE certificate (in the + * SAN extension as dNSName, or in the subjectDN's CN + * if there is no SAN extension). + * The caller ensures that the provided 'server_name' + * pointer remains valid throughout validation. + * + * start_cert Begins a new certificate in the chain. The provided + * length is in bytes; this is the total certificate length. + * + * append Get some additional bytes for the current certificate. + * + * end_cert Ends the current certificate. + * + * end_chain Called at the end of the chain. Returned value is + * 0 on success, or a non-zero error code. + * + * get_pkey Returns the EE certificate public key. + * + * For a complete chain, start_chain() and end_chain() are always + * called. For each certificate, start_cert(), some append() calls, then + * end_cert() are called, in that order. There may be no append() call + * at all if the certificate is empty (which is not valid but may happen + * if the peer sends exactly that). + * + * get_pkey() shall return a pointer to a structure that is valid as + * long as a new chain is not started. This may be a sub-structure + * within the context for the engine. This function MAY return a valid + * pointer to a public key even in some cases of validation failure, + * depending on the validation engine. + */ + +/** + * \brief Class type for an X.509 engine. + * + * A certificate chain validation uses a caller-allocated context, which + * contains the running state for that validation. Methods are called + * in due order: + * + * - `start_chain()` is called at the start of the validation. + * - Certificates are processed one by one, in SSL order (end-entity + * comes first). For each certificate, the following methods are + * called: + * + * - `start_cert()` at the beginning of the certificate. + * - `append()` is called zero, one or more times, to provide + * the certificate (possibly in chunks). + * - `end_cert()` at the end of the certificate. + * + * - `end_chain()` is called when the last certificate in the chain + * was processed. + * - `get_pkey()` is called after chain processing, if the chain + * validation was successful. + * + * A context structure may be reused; the `start_chain()` method shall + * ensure (re)initialisation. + */ +typedef struct br_x509_class_ br_x509_class; +struct br_x509_class_ { + /** + * \brief X.509 context size, in bytes. + */ + size_t context_size; + + /** + * \brief Start a new chain. + * + * This method shall set the vtable (first field) of the context + * structure. + * + * The `server_name`, if not `NULL`, will be considered as a + * fully qualified domain name, to be matched against the `dNSName` + * elements of the end-entity certificate's SAN extension (if there + * is no SAN, then the Common Name from the subjectDN will be used). + * If `server_name` is `NULL` then no such matching is performed. + * + * \param ctx validation context. + * \param server_name server name to match (or `NULL`). + */ + void (*start_chain)(const br_x509_class **ctx, + const char *server_name); + + /** + * \brief Start a new certificate. + * + * \param ctx validation context. + * \param length new certificate length (in bytes). + */ + void (*start_cert)(const br_x509_class **ctx, uint32_t length); + + /** + * \brief Receive some bytes for the current certificate. + * + * This function may be called several times in succession for + * a given certificate. The caller guarantees that for each + * call, `len` is not zero, and the sum of all chunk lengths + * for a certificate matches the total certificate length which + * was provided in the previous `start_cert()` call. + * + * If the new certificate is empty (no byte at all) then this + * function won't be called at all. + * + * \param ctx validation context. + * \param buf certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ + void (*append)(const br_x509_class **ctx, + const unsigned char *buf, size_t len); + + /** + * \brief Finish the current certificate. + * + * This function is called when the end of the current certificate + * is reached. + * + * \param ctx validation context. + */ + void (*end_cert)(const br_x509_class **ctx); + + /** + * \brief Finish the chain. + * + * This function is called at the end of the chain. It shall + * return either 0 if the validation was successful, or a + * non-zero error code. The `BR_ERR_X509_*` constants are + * error codes, though other values may be possible. + * + * \param ctx validation context. + * \return 0 on success, or a non-zero error code. + */ + unsigned (*end_chain)(const br_x509_class **ctx); + + /** + * \brief Get the resulting end-entity public key. + * + * The decoded public key is returned. The returned pointer + * may be valid only as long as the context structure is + * unmodified, i.e. it may cease to be valid if the context + * is released or reused. + * + * This function _may_ return `NULL` if the validation failed. + * However, returning a public key does not mean that the + * validation was wholly successful; some engines may return + * a decoded public key even if the chain did not end on a + * trusted anchor. + * + * If validation succeeded and `usage` is not `NULL`, then + * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN` + * and/or `BR_KEYTYPE_KEYX` that specifies the validated key + * usage types. It is the caller's responsibility to check + * that value against the intended use of the public key. + * + * \param ctx validation context. + * \return the end-entity public key, or `NULL`. + */ + const br_x509_pkey *(*get_pkey)( + const br_x509_class *const *ctx, unsigned *usages); +}; + +/** + * \brief The "known key" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "known key" engine returns an externally configured public key, + * and totally ignores the certificate contents. + */ +typedef struct { + /** \brief Reference to the context vtable. */ + const br_x509_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_x509_pkey pkey; + unsigned usages; +#endif +} br_x509_knownkey_context; + +/** + * \brief Class instance for the "known key" X.509 engine. + */ +extern const br_x509_class br_x509_knownkey_vtable; + +/** + * \brief Initialize a "known key" X.509 engine with a known RSA public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, + const br_rsa_public_key *pk, unsigned usages); + +/** + * \brief Initialize a "known key" X.509 engine with a known EC public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, + const br_ec_public_key *pk, unsigned usages); + +#ifndef BR_DOXYGEN_IGNORE +/* + * The minimal X.509 engine has some state buffers which must be large + * enough to simultaneously accommodate: + * -- the public key extracted from the current certificate; + * -- the signature on the current certificate or on the previous + * certificate; + * -- the public key extracted from the EE certificate. + * + * We store public key elements in their raw unsigned big-endian + * encoding. We want to support up to RSA-4096 with a short (up to 64 + * bits) public exponent, thus a buffer for a public key must have + * length at least 520 bytes. Similarly, a RSA-4096 signature has length + * 512 bytes. + * + * Though RSA public exponents can formally be as large as the modulus + * (mathematically, even larger exponents would work, but PKCS#1 forbids + * them), exponents that do not fit on 32 bits are extremely rare, + * notably because some widespread implementations (e.g. Microsoft's + * CryptoAPI) don't support them. Moreover, large public exponent do not + * seem to imply any tangible security benefit, and they increase the + * cost of public key operations. The X.509 "minimal" engine will tolerate + * public exponents of arbitrary size as long as the modulus and the + * exponent can fit together in the dedicated buffer. + * + * EC public keys are shorter than RSA public keys; even with curve + * NIST P-521 (the largest curve we care to support), a public key is + * encoded over 133 bytes only. + */ +#define BR_X509_BUFSIZE_KEY 520 +#define BR_X509_BUFSIZE_SIG 512 +#endif + +/** + * \brief Type for receiving a name element. + * + * An array of such structures can be provided to the X.509 decoding + * engines. If the specified elements are found in the certificate + * subject DN or the SAN extension, then the name contents are copied + * as zero-terminated strings into the buffer. + * + * The decoder converts TeletexString and BMPString to UTF8String, and + * ensures that the resulting string is zero-terminated. If the string + * does not fit in the provided buffer, then the copy is aborted and an + * error is reported. + */ +typedef struct { + /** + * \brief Element OID. + * + * For X.500 name elements (to be extracted from the subject DN), + * this is the encoded OID for the requested name element; the + * first byte shall contain the length of the DER-encoded OID + * value, followed by the OID value (for instance, OID 2.5.4.3, + * for id-at-commonName, will be `03 55 04 03`). This is + * equivalent to full DER encoding with the length but without + * the tag. + * + * For SAN name elements, the first byte (`oid[0]`) has value 0, + * followed by another byte that matches the expected GeneralName + * tag. Allowed second byte values are then: + * + * - 1: `rfc822Name` + * + * - 2: `dNSName` + * + * - 6: `uniformResourceIdentifier` + * + * - 0: `otherName` + * + * If first and second byte are 0, then this is a SAN element of + * type `otherName`; the `oid[]` array should then contain, right + * after the two bytes of value 0, an encoded OID (with the same + * conventions as for X.500 name elements). If a match is found + * for that OID, then the corresponding name element will be + * extracted, as long as it is a supported string type. + */ + const unsigned char *oid; + + /** + * \brief Destination buffer. + */ + char *buf; + + /** + * \brief Length (in bytes) of the destination buffer. + * + * The buffer MUST NOT be smaller than 1 byte. + */ + size_t len; + + /** + * \brief Decoding status. + * + * Status is 0 if the name element was not found, 1 if it was + * found and decoded, or -1 on error. Error conditions include + * an unrecognised encoding, an invalid encoding, or a string + * too large for the destination buffer. + */ + int status; + +} br_name_element; + +/** + * \brief Callback for validity date checks. + * + * The function receives as parameter an arbitrary user-provided context, + * and the notBefore and notAfter dates specified in an X.509 certificate, + * both expressed as a number of days and a number of seconds: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * Each date and time is understood in the UTC time zone. The "Unix + * Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and + * seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * This function must return -1 if the current date is strictly before + * the "notBefore" time, or +1 if the current date is strictly after the + * "notAfter" time. If neither condition holds, then the function returns + * 0, which means that the current date falls within the validity range of + * the certificate. If the function returns a value distinct from -1, 0 + * and +1, then this is interpreted as an unavailability of the current + * time, which normally ends the validation process with a + * `BR_ERR_X509_TIME_UNKNOWN` error. + * + * During path validation, this callback will be invoked for each + * considered X.509 certificate. Validation fails if any of the calls + * returns a non-zero value. + * + * The context value is an abritrary pointer set by the caller when + * configuring this callback. + * + * \param tctx context pointer. + * \param not_before_days notBefore date (days since Jan 1st, 0 AD). + * \param not_before_seconds notBefore time (seconds, at most 86400). + * \param not_after_days notAfter date (days since Jan 1st, 0 AD). + * \param not_after_seconds notAfter time (seconds, at most 86400). + * \return -1, 0 or +1. + */ +typedef int (*br_x509_time_check)(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds); + +/** + * \brief The "minimal" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "minimal" engine performs a rudimentary but serviceable X.509 path + * validation. + */ +typedef struct { + const br_x509_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the EE public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[31]; + uint32_t rp_stack[31]; + int err; + + /* Server name to match with the SAN / CN of the EE certificate. */ + const char *server_name; + + /* Validated key usages. */ + unsigned char key_usages; + + /* Explicitly set date and time. */ + uint32_t days, seconds; + + /* Current certificate length (in bytes). Set to 0 when the + certificate has been fully processed. */ + uint32_t cert_length; + + /* Number of certificates processed so far in the current chain. + It is incremented at the end of the processing of a certificate, + so it is 0 for the EE. */ + uint32_t num_certs; + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Buffer for EE public key data. */ + unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Buffer for currently decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Signature type: signer key type, offset to the hash + function OID (in the T0 data block) and hash function + output length (TBS hash length). */ + unsigned char cert_signer_key_type; + uint16_t cert_sig_hash_oid; + unsigned char cert_sig_hash_len; + + /* Current/last certificate signature. */ + unsigned char cert_sig[BR_X509_BUFSIZE_SIG]; + uint16_t cert_sig_len; + + /* Minimum RSA key length (difference in bytes from 128). */ + int16_t min_rsa_size; + + /* Configured trust anchors. */ + const br_x509_trust_anchor *trust_anchors; + size_t trust_anchors_num; + + /* + * Multi-hasher for the TBS. + */ + unsigned char do_mhash; + br_multihash_context mhash; + unsigned char tbs_hash[64]; + + /* + * Simple hasher for the subject/issuer DN. + */ + unsigned char do_dn_hash; + const br_hash_class *dn_hash_impl; + br_hash_compat_context dn_hash; + unsigned char current_dn_hash[64]; + unsigned char next_dn_hash[64]; + unsigned char saved_dn_hash[64]; + + /* + * Name elements to gather. + */ + br_name_element *name_elts; + size_t num_name_elts; + + /* + * Callback function (and context) to get the current date. + */ + void *itime_ctx; + br_x509_time_check itime; + + /* + * Public key cryptography implementations (signature verification). + */ + br_rsa_pkcs1_vrfy irsa; + br_ecdsa_vrfy iecdsa; + const br_ec_impl *iec; +#endif + +} br_x509_minimal_context; + +/** + * \brief Class instance for the "minimal" X.509 engine. + */ +extern const br_x509_class br_x509_minimal_vtable; + +/** + * \brief Initialise a "minimal" X.509 engine. + * + * The `dn_hash_impl` parameter shall be a hash function internally used + * to match X.500 names (subject/issuer DN, and anchor names). Any standard + * hash function may be used, but a collision-resistant hash function is + * advised. + * + * After initialization, some implementations for signature verification + * (hash functions and signature algorithms) MUST be added. + * + * \param ctx context to initialise. + * \param dn_hash_impl hash function for DN comparisons. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set a supported hash function in an X.509 "minimal" engine. + * + * Hash functions are used with signature verification algorithms. + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the hash functions it shall support for that + * purpose. The hash function identifier MUST be one of the standard + * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 and SHA-512). + * + * If `impl` is `NULL`, this _removes_ support for the designated + * hash function. + * + * \param ctx validation context. + * \param id hash function identifier (from 1 to 6). + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_x509_minimal_set_hash(br_x509_minimal_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Set a RSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. If `irsa` is `0`, then the RSA support + * is disabled. + * + * \param ctx validation context. + * \param irsa RSA signature verification implementation (or `0`). + */ +static inline void +br_x509_minimal_set_rsa(br_x509_minimal_context *ctx, + br_rsa_pkcs1_vrfy irsa) +{ + ctx->irsa = irsa; +} + +/** + * \brief Set a ECDSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. + * + * If `iecdsa` is `0`, then this call disables ECDSA support; in that + * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function + * that verifies ECDSA signatures with format "asn1", and it will use + * `iec` as underlying elliptic curve support. + * + * \param ctx validation context. + * \param iec elliptic curve implementation (or `NULL`). + * \param iecdsa ECDSA implementation (or `0`). + */ +static inline void +br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, + const br_ec_impl *iec, br_ecdsa_vrfy iecdsa) +{ + ctx->iecdsa = iecdsa; + ctx->iec = iec; +} + +/** + * \brief Initialise a "minimal" X.509 engine with default algorithms. + * + * This function performs the same job as `br_x509_minimal_init()`, but + * also sets implementations for RSA, ECDSA, and the standard hash + * functions. + * + * \param ctx context to initialise. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init_full(br_x509_minimal_context *ctx, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set the validation time for the X.509 "minimal" engine. + * + * The validation time is set as two 32-bit integers, for days and + * seconds since a fixed epoch: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * The validation date and time is understood in the UTC time zone. The + * "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 + * and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * If the validation date and time are not explicitly set, but BearSSL + * was compiled with support for the system clock on the underlying + * platform, then the current time will automatically be used. Otherwise, + * not setting the validation date and time implies a validation + * failure (except in case of direct trust of the EE key). + * + * \param ctx validation context. + * \param days days since January 1st, 0 AD (Gregorian calendar). + * \param seconds seconds since midnight (0 to 86400). + */ +static inline void +br_x509_minimal_set_time(br_x509_minimal_context *ctx, + uint32_t days, uint32_t seconds) +{ + ctx->days = days; + ctx->seconds = seconds; + ctx->itime = 0; +} + +/** + * \brief Set the validity range callback function for the X.509 + * "minimal" engine. + * + * The provided function will be invoked to check whether the validation + * date is within the validity range for a given X.509 certificate; a + * call will be issued for each considered certificate. The provided + * context pointer (itime_ctx) will be passed as first parameter to the + * callback. + * + * \param tctx context for callback invocation. + * \param cb callback function. + */ +static inline void +br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx, + void *itime_ctx, br_x509_time_check itime) +{ + ctx->itime_ctx = itime_ctx; + ctx->itime = itime; +} + +/** + * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal" + * engine). + * + * The RSA key length is expressed in bytes. The default minimum key + * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter + * than the configured length will be rejected, implying validation + * failure. This setting applies to keys extracted from certificates + * (both end-entity, and intermediate CA) but not to "CA" trust anchors. + * + * \param ctx validation context. + * \param byte_length minimum RSA key length, **in bytes** (not bits). + */ +static inline void +br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) +{ + ctx->min_rsa_size = (int16_t)(byte_length - 128); +} + +/** + * \brief Set the name elements to gather. + * + * The provided array is linked in the context. The elements are + * gathered from the EE certificate. If the same element type is + * requested several times, then the relevant structures will be filled + * in the order the matching values are encountered in the certificate. + * + * \param ctx validation context. + * \param elts array of name element structures to fill. + * \param num_elts number of name element structures to fill. + */ +static inline void +br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, + br_name_element *elts, size_t num_elts) +{ + ctx->name_elts = elts; + ctx->num_name_elts = num_elts; +} + +/** + * \brief X.509 decoder context. + * + * This structure is _not_ for X.509 validation, but for extracting + * names and public keys from encoded certificates. Intended usage is + * to use (self-signed) certificates as trust anchors. + * + * Contents are opaque and shall not be accessed directly. + */ +typedef struct { + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Flag set when decoding succeeds. */ + unsigned char decoded; + + /* Validity dates. */ + uint32_t notbefore_days, notbefore_seconds; + uint32_t notafter_days, notafter_seconds; + + /* The "CA" flag. This is set to true if the certificate contains + a Basic Constraints extension that asserts CA status. */ + unsigned char isCA; + + /* DN processing: the subject DN is extracted and pushed to the + provided callback. */ + unsigned char copy_dn; + void *append_dn_ctx; + void (*append_dn)(void *ctx, const void *buf, size_t len); + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* Buffer for decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Type of key and hash function used in the certificate signature. */ + unsigned char signer_key_type; + unsigned char signer_hash_id; +#endif + +} br_x509_decoder_context; + +/** + * \brief Initialise an X.509 decoder context for processing a new + * certificate. + * + * The `append_dn()` callback (with opaque context `append_dn_ctx`) + * will be invoked to receive, chunk by chunk, the certificate's + * subject DN. If `append_dn` is `0` then the subject DN will be + * ignored. + * + * \param ctx X.509 decoder context to initialise. + * \param append_dn DN receiver callback (or `0`). + * \param append_dn_ctx context for the DN receiver callback. + */ +void br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx); + +/** + * \brief Push some certificate bytes into a decoder context. + * + * If `len` is non-zero, then that many bytes are pushed, from address + * `data`, into the provided decoder context. + * + * \param ctx X.509 decoder context. + * \param data certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ +void br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Obtain the decoded public key. + * + * Returned value is a pointer to a structure internal to the decoder + * context; releasing or reusing the decoder context invalidates that + * structure. + * + * If decoding was not finished, or failed, then `NULL` is returned. + * + * \param ctx X.509 decoder context. + * \return the public key, or `NULL` on unfinished/error. + */ +static inline br_x509_pkey * +br_x509_decoder_get_pkey(br_x509_decoder_context *ctx) +{ + if (ctx->decoded && ctx->err == 0) { + return &ctx->pkey; + } else { + return NULL; + } +} + +/** + * \brief Get decoder error status. + * + * If no error was reported yet but the certificate decoding is not + * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding + * was successful, then 0 is returned. + * + * \param ctx X.509 decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_x509_decoder_last_error(br_x509_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (!ctx->decoded) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the "isCA" flag from an X.509 decoder context. + * + * This flag is set if the decoded certificate claims to be a CA through + * a Basic Constraints extension. This flag should not be read before + * decoding completed successfully. + * + * \param ctx X.509 decoder context. + * \return the "isCA" flag. + */ +static inline int +br_x509_decoder_isCA(br_x509_decoder_context *ctx) +{ + return ctx->isCA; +} + +/** + * \brief Get the issuing CA key type (type of algorithm used to sign the + * decoded certificate). + * + * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned + * if the signature type was not recognised. + * + * \param ctx X.509 decoder context. + * \return the issuing CA key type. + */ +static inline int +br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx) +{ + return ctx->signer_key_type; +} + +/** + * \brief Get the identifier for the hash function used to sign the decoded + * certificate. + * + * This is 0 if the hash function was not recognised. + * + * \param ctx X.509 decoder context. + * \return the signature hash function identifier. + */ +static inline int +br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx) +{ + return ctx->signer_hash_id; +} + +/** + * \brief Type for an X.509 certificate (DER-encoded). + */ +typedef struct { + /** \brief The DER-encoded certificate data. */ + unsigned char *data; + /** \brief The DER-encoded certificate length (in bytes). */ + size_t data_len; +} br_x509_certificate; + +/** + * \brief Private key decoder context. + * + * The private key decoder recognises RSA and EC private keys, either in + * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 + * archive (again DER-encoded). + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the private key. */ + union { + br_rsa_private_key rsa; + br_ec_private_key ec; + } key; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Private key data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Decoded key type; 0 until decoding is complete. */ + unsigned char key_type; + + /* Buffer for the private key elements. It shall be large enough + to accommodate all elements for a RSA-4096 private key (roughly + five 2048-bit integers, possibly a bit more). */ + unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; +#endif +} br_skey_decoder_context; + +/** + * \brief Initialise a private key decoder context. + * + * \param ctx key decoder context to initialise. + */ +void br_skey_decoder_init(br_skey_decoder_context *ctx); + +/** + * \brief Push some data bytes into a private key decoder context. + * + * If `len` is non-zero, then that many data bytes, starting at address + * `data`, are pushed into the decoder. + * + * \param ctx key decoder context. + * \param data private key data chunk. + * \param len private key data chunk length (in bytes). + */ +void br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Get the decoding status for a private key. + * + * Decoding status is 0 on success, or a non-zero error code. If the + * decoding is unfinished when this function is called, then the + * status code `BR_ERR_X509_TRUNCATED` is returned. + * + * \param ctx key decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_skey_decoder_last_error(const br_skey_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (ctx->key_type == 0) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the decoded private key type. + * + * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is + * not finished or failed, then 0 is returned. + * + * \param ctx key decoder context. + * \return decoded private key type, or 0. + */ +static inline int +br_skey_decoder_key_type(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0) { + return ctx->key_type; + } else { + return 0; + } +} + +/** + * \brief Get the decoded RSA private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not RSA. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded RSA private key, or `NULL`. + */ +static inline const br_rsa_private_key * +br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { + return &ctx->key.rsa; + } else { + return NULL; + } +} + +/** + * \brief Get the decoded EC private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not EC. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded EC private key, or `NULL`. + */ +static inline const br_ec_private_key * +br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { + return &ctx->key.ec; + } else { + return NULL; + } +} + +/** + * \brief Encode an RSA private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER + * encoding rules. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an RSA private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" + * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an EC private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is `NULL`, then the encoded key will not include the public key + * in its `publicKey` field (which is nominally optional). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief Encode an EC private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). The curve is identified + * by an OID provided as parameters to the `privateKeyAlgorithm` + * field. The private key value (contents of the `privateKey` field) + * contains the DER encoding of the `ECPrivateKey` type defined in + * RFC 5915, without the `parameters` field (since they would be + * redundant with the information in `privateKeyAlgorithm`). + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is not `NULL`, then the encoded public key is included in the + * `publicKey` field of the private key value (but not in the `publicKey` + * field of the PKCS#8 `OneAsymmetricKey` wrapper). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief PEM banner for RSA private key (raw). + */ +#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" + +/** + * \brief PEM banner for EC private key (raw). + */ +#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" + +/** + * \brief PEM banner for an RSA or EC private key in PKCS#8 format. + */ +#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/template/sysroot/include/bit b/template/sysroot/include/bit new file mode 100644 index 0000000..3e07dd7 --- /dev/null +++ b/template/sysroot/include/bit @@ -0,0 +1,486 @@ +// -*- C++ -*- + +// Copyright (C) 2018-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bit + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BIT +#define _GLIBCXX_BIT 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +#include // for std::integral +#include + +#if _GLIBCXX_HOSTED || __has_include() +# include +#else +# include +/// @cond undocumented +namespace __gnu_cxx +{ + template + struct __int_traits + { + static constexpr int __digits = std::numeric_limits<_Tp>::digits; + static constexpr _Tp __max = std::numeric_limits<_Tp>::max(); + }; +} +/// @endcond +#endif + +#define __glibcxx_want_bit_cast +#define __glibcxx_want_byteswap +#define __glibcxx_want_bitops +#define __glibcxx_want_int_pow2 +#define __glibcxx_want_endian +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup bit_manip Bit manipulation + * @ingroup numerics + * + * Utilities for examining and manipulating individual bits. + * + * @{ + */ + +#ifdef __cpp_lib_bit_cast // C++ >= 20 + + /// Create a value of type `To` from the bits of `from`. + /** + * @tparam _To A trivially-copyable type. + * @param __from A trivially-copyable object of the same size as `_To`. + * @return An object of type `_To`. + * @since C++20 + */ + template + [[nodiscard]] + constexpr _To + bit_cast(const _From& __from) noexcept +#ifdef __cpp_concepts + requires (sizeof(_To) == sizeof(_From)) + && is_trivially_copyable_v<_To> && is_trivially_copyable_v<_From> +#endif + { + return __builtin_bit_cast(_To, __from); + } +#endif // __cpp_lib_bit_cast + +#ifdef __cpp_lib_byteswap // C++ >= 23 + + /// Reverse order of bytes in the object representation of `value`. + /** + * @tparam _Tp An integral type. + * @param __value An object of integer type. + * @return An object of the same type, with the bytes reversed. + * @since C++23 + */ + template + [[nodiscard]] + constexpr _Tp + byteswap(_Tp __value) noexcept + { + if constexpr (sizeof(_Tp) == 1) + return __value; +#if __cpp_if_consteval >= 202106L && __CHAR_BIT__ == 8 + if !consteval + { + if constexpr (sizeof(_Tp) == 2) + return __builtin_bswap16(__value); + if constexpr (sizeof(_Tp) == 4) + return __builtin_bswap32(__value); + if constexpr (sizeof(_Tp) == 8) + return __builtin_bswap64(__value); + if constexpr (sizeof(_Tp) == 16) +#if __has_builtin(__builtin_bswap128) + return __builtin_bswap128(__value); +#else + return (__builtin_bswap64(__value >> 64) + | (static_cast<_Tp>(__builtin_bswap64(__value)) << 64)); +#endif + } +#endif + + // Fallback implementation that handles even __int24 etc. + using _Up = typename __make_unsigned<__remove_cv_t<_Tp>>::__type; + size_t __diff = __CHAR_BIT__ * (sizeof(_Tp) - 1); + _Up __mask1 = static_cast(~0); + _Up __mask2 = __mask1 << __diff; + _Up __val = __value; + for (size_t __i = 0; __i < sizeof(_Tp) / 2; ++__i) + { + _Up __byte1 = __val & __mask1; + _Up __byte2 = __val & __mask2; + __val = (__val ^ __byte1 ^ __byte2 + ^ (__byte1 << __diff) ^ (__byte2 >> __diff)); + __mask1 <<= __CHAR_BIT__; + __mask2 >>= __CHAR_BIT__; + __diff -= 2 * __CHAR_BIT__; + } + return __val; + } +#endif // __cpp_lib_byteswap + + /// @cond undocumented + + template + constexpr _Tp + __rotl(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0) + { + // Variant for power of two _Nd which the compiler can + // easily pattern match. + constexpr unsigned __uNd = _Nd; + const unsigned __r = __s; + return (__x << (__r % __uNd)) | (__x >> ((-__r) % __uNd)); + } + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); + else + return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) + } + + template + constexpr _Tp + __rotr(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0) + { + // Variant for power of two _Nd which the compiler can + // easily pattern match. + constexpr unsigned __uNd = _Nd; + const unsigned __r = __s; + return (__x >> (__r % __uNd)) | (__x << ((-__r) % __uNd)); + } + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); + else + return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) + } + + template + constexpr int + __countl_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + { + constexpr int __diff = _Nd_u - _Nd; + return __builtin_clz(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + { + constexpr int __diff = _Nd_ul - _Nd; + return __builtin_clzl(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + { + constexpr int __diff = _Nd_ull - _Nd; + return __builtin_clzll(__x) - __diff; + } + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + unsigned long long __high = __x >> _Nd_ull; + if (__high != 0) + { + constexpr int __diff = (2 * _Nd_ull) - _Nd; + return __builtin_clzll(__high) - __diff; + } + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + return (_Nd - _Nd_ull) + __builtin_clzll(__low); + } + } + + template + constexpr int + __countl_one(_Tp __x) noexcept + { + return std::__countl_zero<_Tp>((_Tp)~__x); + } + + template + constexpr int + __countr_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_ctz(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_ctzl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_ctzll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + if (__low != 0) + return __builtin_ctzll(__low); + unsigned long long __high = __x >> _Nd_ull; + return __builtin_ctzll(__high) + _Nd_ull; + } + } + + template + constexpr int + __countr_one(_Tp __x) noexcept + { + return std::__countr_zero((_Tp)~__x); + } + + template + constexpr int + __popcount(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_popcount(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_popcountl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_popcountll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + unsigned long long __high = __x >> _Nd_ull; + return __builtin_popcountll(__low) + __builtin_popcountll(__high); + } + } + + template + constexpr bool + __has_single_bit(_Tp __x) noexcept + { return std::__popcount(__x) == 1; } + + template + constexpr _Tp + __bit_ceil(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + if (__x == 0 || __x == 1) + return 1; + auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); + // If the shift exponent equals _Nd then the correct result is not + // representable as a value of _Tp, and so the result is undefined. + // Want that undefined behaviour to be detected in constant expressions, + // by UBSan, and by debug assertions. + if (!std::__is_constant_evaluated()) + { + __glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits ); + } + + using __promoted_type = decltype(__x << 1); + if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) + { + // If __x undergoes integral promotion then shifting by _Nd is + // not undefined. In order to make the shift undefined, so that + // it is diagnosed in constant expressions and by UBsan, we also + // need to "promote" the shift exponent to be too large for the + // promoted type. + const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; + __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; + } + return (_Tp)1u << __shift_exponent; + } + + template + constexpr _Tp + __bit_floor(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + if (__x == 0) + return 0; + return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); + } + + template + constexpr int + __bit_width(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + return _Nd - std::__countl_zero(__x); + } + + /// @endcond + +#ifdef __cpp_lib_bitops // C++ >= 20 + + /// @cond undocumented + template + concept __unsigned_integer = __is_unsigned_integer<_Tp>::value; + /// @endcond + + // [bit.rot], rotating + + /// Rotate `x` to the left by `s` bits. + template<__unsigned_integer _Tp> + [[nodiscard]] constexpr _Tp + rotl(_Tp __x, int __s) noexcept + { return std::__rotl(__x, __s); } + + /// Rotate `x` to the right by `s` bits. + template<__unsigned_integer _Tp> + [[nodiscard]] constexpr _Tp + rotr(_Tp __x, int __s) noexcept + { return std::__rotr(__x, __s); } + + // [bit.count], counting + + /// The number of contiguous zero bits, starting from the highest bit. + template<__unsigned_integer _Tp> + constexpr int + countl_zero(_Tp __x) noexcept + { return std::__countl_zero(__x); } + + /// The number of contiguous one bits, starting from the highest bit. + template<__unsigned_integer _Tp> + constexpr int + countl_one(_Tp __x) noexcept + { return std::__countl_one(__x); } + + /// The number of contiguous zero bits, starting from the lowest bit. + template<__unsigned_integer _Tp> + constexpr int + countr_zero(_Tp __x) noexcept + { return std::__countr_zero(__x); } + + /// The number of contiguous one bits, starting from the lowest bit. + template<__unsigned_integer _Tp> + constexpr int + countr_one(_Tp __x) noexcept + { return std::__countr_one(__x); } + + /// The number of bits set in `x`. + template<__unsigned_integer _Tp> + constexpr int + popcount(_Tp __x) noexcept + { return std::__popcount(__x); } +#endif // __cpp_lib_bitops + +#ifdef __cpp_lib_int_pow2 // C++ >= 20 + // [bit.pow.two], integral powers of 2 + + /// True if `x` is a power of two, false otherwise. + template<__unsigned_integer _Tp> + constexpr bool + has_single_bit(_Tp __x) noexcept + { return std::__has_single_bit(__x); } + + /// The smallest power-of-two not less than `x`. + template<__unsigned_integer _Tp> + constexpr _Tp + bit_ceil(_Tp __x) noexcept + { return std::__bit_ceil(__x); } + + /// The largest power-of-two not greater than `x`. + template<__unsigned_integer _Tp> + constexpr _Tp + bit_floor(_Tp __x) noexcept + { return std::__bit_floor(__x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3656. Inconsistent bit operations returning a count + /// The smallest integer greater than the base-2 logarithm of `x`. + template<__unsigned_integer _Tp> + constexpr int + bit_width(_Tp __x) noexcept + { return std::__bit_width(__x); } +#endif // defined (__cpp_lib_int_pow2) + +#ifdef __cpp_lib_endian // C++ >= 20 + + /// Byte order constants + /** + * The platform endianness can be checked by comparing `std::endian::native` + * to one of `std::endian::big` or `std::endian::little`. + * + * @since C++20 + */ + enum class endian + { + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ + }; +#endif // __cpp_lib_endian + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 +#endif // _GLIBCXX_BIT diff --git a/template/sysroot/include/bits/algorithmfwd.h b/template/sysroot/include/bits/algorithmfwd.h new file mode 100644 index 0000000..34bf992 --- /dev/null +++ b/template/sysroot/include/bits/algorithmfwd.h @@ -0,0 +1,970 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/algorithmfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_ALGORITHMFWD_H +#define _GLIBCXX_ALGORITHMFWD_H 1 + +#pragma GCC system_header + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + adjacent_find + all_of (C++11) + any_of (C++11) + binary_search + clamp (C++17) + copy + copy_backward + copy_if (C++11) + copy_n (C++11) + count + count_if + equal + equal_range + fill + fill_n + find + find_end + find_first_of + find_if + find_if_not (C++11) + for_each + generate + generate_n + includes + inplace_merge + is_heap (C++11) + is_heap_until (C++11) + is_partitioned (C++11) + is_sorted (C++11) + is_sorted_until (C++11) + iter_swap + lexicographical_compare + lower_bound + make_heap + max + max_element + merge + min + min_element + minmax (C++11) + minmax_element (C++11) + mismatch + next_permutation + none_of (C++11) + nth_element + partial_sort + partial_sort_copy + partition + partition_copy (C++11) + partition_point (C++11) + pop_heap + prev_permutation + push_heap + random_shuffle + remove + remove_copy + remove_copy_if + remove_if + replace + replace_copy + replace_copy_if + replace_if + reverse + reverse_copy + rotate + rotate_copy + search + search_n + set_difference + set_intersection + set_symmetric_difference + set_union + shuffle (C++11) + sort + sort_heap + stable_partition + stable_sort + swap + swap_ranges + transform + unique + unique_copy + upper_bound + */ + + /** + * @defgroup algorithms Algorithms + * + * Components for performing algorithmic operations. Includes + * non-modifying sequence, modifying (mutating) sequence, sorting, + * searching, merge, partition, heap, set, minima, maxima, and + * permutation operations. + */ + + /** + * @defgroup mutating_algorithms Mutating + * @ingroup algorithms + */ + + /** + * @defgroup non_mutating_algorithms Non-Mutating + * @ingroup algorithms + */ + + /** + * @defgroup sorting_algorithms Sorting + * @ingroup algorithms + */ + + /** + * @defgroup set_algorithms Set Operations + * @ingroup sorting_algorithms + * + * These algorithms are common set operations performed on sequences + * that are already sorted. The number of comparisons will be + * linear. + */ + + /** + * @defgroup binary_search_algorithms Binary Search + * @ingroup sorting_algorithms + * + * These algorithms are variations of a classic binary search, and + * all assume that the sequence being searched is already sorted. + * + * The number of comparisons will be logarithmic (and as few as + * possible). The number of steps through the sequence will be + * logarithmic for random-access iterators (e.g., pointers), and + * linear otherwise. + * + * The LWG has passed Defect Report 270, which notes: The + * proposed resolution reinterprets binary search. Instead of + * thinking about searching for a value in a sorted range, we view + * that as an important special case of a more general algorithm: + * searching for the partition point in a partitioned range. We + * also add a guarantee that the old wording did not: we ensure that + * the upper bound is no earlier than the lower bound, that the pair + * returned by equal_range is a valid range, and that the first part + * of that pair is the lower bound. + * + * The actual effect of the first sentence is that a comparison + * functor passed by the user doesn't necessarily need to induce a + * strict weak ordering relation. Rather, it partitions the range. + */ + + // adjacent_find + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + all_of(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + any_of(_IIter, _IIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&, _Compare); + +#if __cplusplus > 201402L + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _BIter2 + copy_backward(_BIter1, _BIter1, _BIter2); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_if(_IIter, _IIter, _OIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_n(_IIter, _Size, _OIter); +#endif + + // count + // count_if + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + fill(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + fill_n(_OIter, _Size, const _Tp&); + + // find + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + // find_first_of + // find_if + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if_not(_IIter, _IIter, _Predicate); +#endif + + // for_each + // generate + // generate_n + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + void + inplace_merge(_BIter, _BIter, _BIter); + + template + void + inplace_merge(_BIter, _BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + is_partitioned(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + iter_swap(_FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&, _Compare); + + // max_element + // merge + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&, _Compare); + + // min_element + +#if __cplusplus >= 201103L + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>, _Compare); +#endif + + // mismatch + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + none_of(_IIter, _IIter, _Predicate); +#endif + + // nth_element + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare); + + // partition + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + pair<_OIter1, _OIter2> + partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + partition_point(_FIter, _FIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter, _Compare); + + // random_shuffle + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove_if(_FIter, _FIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy(_IIter, _IIter, _OIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy_if(_IIter, _IIter, _OIter, _Predicate); + + // replace + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); + + // replace_if + + template + _GLIBCXX20_CONSTEXPR + void + reverse(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + reverse_copy(_BIter, _BIter, _OIter); + +_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) + + template + _GLIBCXX20_CONSTEXPR + _FIter + rotate(_FIter, _FIter, _FIter); + +_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) + + template + _GLIBCXX20_CONSTEXPR + _OIter + rotate_copy(_FIter, _FIter, _FIter, _OIter); + + // search + // search_n + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + +#if __cplusplus >= 201103L + template + void + shuffle(_RAIter, _RAIter, _UGenerator&&); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter, _Compare); + +#if _GLIBCXX_HOSTED + template + _BIter + stable_partition(_BIter, _BIter, _Predicate); +#endif + +#if __cplusplus < 201103L + // For C++11 swap() is declared in . + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp& __a, _Tp& __b); + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]); +#endif + + template + _GLIBCXX20_CONSTEXPR + _FIter2 + swap_ranges(_FIter1, _FIter1, _FIter2); + + // transform + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter, _BinaryPredicate); + + // unique_copy + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&, _Compare); + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _Funct + for_each(_IIter, _IIter, _Funct); + + template + _GLIBCXX20_CONSTEXPR + void + generate(_FIter, _FIter, _Generator); + + template + _GLIBCXX20_CONSTEXPR + _OIter + generate_n(_OIter, _Size, _Generator); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _BIter + partition(_BIter, _BIter, _Predicate); + +#if _GLIBCXX_HOSTED + template + _GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle") + void + random_shuffle(_RAIter, _RAIter); + + template + _GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle") + void + random_shuffle(_RAIter, _RAIter, +#if __cplusplus >= 201103L + _Generator&&); +#else + _Generator&); +#endif +#endif // HOSTED + + template + _GLIBCXX20_CONSTEXPR + void + replace(_FIter, _FIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_FIter, _FIter, _Predicate, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, + _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter, _Compare); + + template + void + stable_sort(_RAIter, _RAIter); + + template + void + stable_sort(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter, _IIter, _OIter, _UnaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate); + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#ifdef _GLIBCXX_PARALLEL +# include +#endif + +#endif + diff --git a/template/sysroot/include/bits/align.h b/template/sysroot/include/bits/align.h new file mode 100644 index 0000000..1a06b81 --- /dev/null +++ b/template/sysroot/include/bits/align.h @@ -0,0 +1,109 @@ +// align implementation -*- C++ -*- + +// Copyright (C) 2014-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/align.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_ALIGN_H +#define _GLIBCXX_ALIGN_H 1 + +#include // std::has_single_bit +#include // uintptr_t +#include // _GLIBCXX_DEBUG_ASSERT +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Fit aligned storage in buffer. + * + * This function tries to fit @a __size bytes of storage with alignment + * @a __align into the buffer @a __ptr of size @a __space bytes. If such + * a buffer fits then @a __ptr is changed to point to the first byte of the + * aligned storage and @a __space is reduced by the bytes used for alignment. + * + * C++11 20.6.5 [ptr.align] + * + * @param __align A fundamental or extended alignment value. + * @param __size Size of the aligned storage required. + * @param __ptr Pointer to a buffer of @a __space bytes. + * @param __space Size of the buffer pointed to by @a __ptr. + * @return the updated pointer if the aligned storage fits, otherwise nullptr. + * + * @ingroup memory + */ +inline void* +align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept +{ + if (__space < __size) + return nullptr; + const auto __intptr = reinterpret_cast(__ptr); + const auto __aligned = (__intptr - 1u + __align) & -__align; + const auto __diff = __aligned - __intptr; + if (__diff > (__space - __size)) + return nullptr; + else + { + __space -= __diff; + return __ptr = reinterpret_cast(__aligned); + } +} + +#ifdef __glibcxx_assume_aligned // C++ >= 20 + /** @brief Inform the compiler that a pointer is aligned. + * + * @tparam _Align An alignment value (i.e. a power of two) + * @tparam _Tp An object type + * @param __ptr A pointer that is aligned to _Align + * + * C++20 20.10.6 [ptr.align] + * + * @ingroup memory + */ + template + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + assume_aligned(_Tp* __ptr) noexcept + { + static_assert(std::has_single_bit(_Align)); + if (std::is_constant_evaluated()) + return __ptr; + else + { + // This function is expected to be used in hot code, where + // __glibcxx_assert would add unwanted overhead. + _GLIBCXX_DEBUG_ASSERT((uintptr_t)__ptr % _Align == 0); + return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align)); + } + } +#endif // __glibcxx_assume_aligned + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GLIBCXX_ALIGN_H */ diff --git a/template/sysroot/include/bits/alloc_traits.h b/template/sysroot/include/bits/alloc_traits.h new file mode 100644 index 0000000..82fc79c --- /dev/null +++ b/template/sysroot/include/bits/alloc_traits.h @@ -0,0 +1,951 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/alloc_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOC_TRAITS_H +#define _ALLOC_TRAITS_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +# include +# if _GLIBCXX_HOSTED +# include +# endif +# if __cpp_exceptions +# include // __make_move_if_noexcept_iterator +# endif +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201103L + /// @cond undocumented + struct __allocator_traits_base + { + template + struct __rebind : __replace_first_arg<_Tp, _Up> + { + static_assert(is_same< + typename __replace_first_arg<_Tp, typename _Tp::value_type>::type, + _Tp>::value, + "allocator_traits::rebind_alloc must be A"); + }; + + template + struct __rebind<_Tp, _Up, + __void_t::other>> + { + using type = typename _Tp::template rebind<_Up>::other; + + static_assert(is_same< + typename _Tp::template rebind::other, + _Tp>::value, + "allocator_traits::rebind_alloc must be A"); + }; + + protected: + template + using __pointer = typename _Tp::pointer; + template + using __c_pointer = typename _Tp::const_pointer; + template + using __v_pointer = typename _Tp::void_pointer; + template + using __cv_pointer = typename _Tp::const_void_pointer; + template + using __pocca = typename _Tp::propagate_on_container_copy_assignment; + template + using __pocma = typename _Tp::propagate_on_container_move_assignment; + template + using __pocs = typename _Tp::propagate_on_container_swap; + template + using __equal = __type_identity; + }; + + template + using __alloc_rebind + = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; + /// @endcond + + /** + * @brief Uniform interface to all allocator types. + * @headerfile memory + * @ingroup allocators + * @since C++11 + */ + template + struct allocator_traits : __allocator_traits_base + { + /// The allocator type + typedef _Alloc allocator_type; + /// The allocated type + typedef typename _Alloc::value_type value_type; + + /** + * @brief The allocator's pointer type. + * + * @c Alloc::pointer if that type exists, otherwise @c value_type* + */ + using pointer = __detected_or_t; + + private: + // Select _Func<_Alloc> or pointer_traits::rebind<_Tp> + template class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits::template rebind<_Tp>; + }; + + template class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> + { + using type = _Func<_Alloc>; + }; + + // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type + template + struct _Diff + { using type = typename pointer_traits<_PtrT>::difference_type; }; + + template + struct _Diff<_A2, _PtrT, __void_t> + { using type = typename _A2::difference_type; }; + + // Select _A2::size_type or make_unsigned<_DiffT>::type + template + struct _Size : make_unsigned<_DiffT> { }; + + template + struct _Size<_A2, _DiffT, __void_t> + { using type = typename _A2::size_type; }; + + public: + /** + * @brief The allocator's const pointer type. + * + * @c Alloc::const_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; + + /** + * @brief The allocator's void pointer type. + * + * @c Alloc::void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using void_pointer = typename _Ptr<__v_pointer, void>::type; + + /** + * @brief The allocator's const void pointer type. + * + * @c Alloc::const_void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; + + /** + * @brief The allocator's difference type + * + * @c Alloc::difference_type if that type exists, otherwise + * pointer_traits::difference_type + */ + using difference_type = typename _Diff<_Alloc, pointer>::type; + + /** + * @brief The allocator's size type + * + * @c Alloc::size_type if that type exists, otherwise + * make_unsigned::type + */ + using size_type = typename _Size<_Alloc, difference_type>::type; + + /** + * @brief How the allocator is propagated on copy assignment + * + * @c Alloc::propagate_on_container_copy_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_copy_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on move assignment + * + * @c Alloc::propagate_on_container_move_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_move_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on swap + * + * @c Alloc::propagate_on_container_swap if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_swap + = __detected_or_t; + + /** + * @brief Whether all instances of the allocator type compare equal. + * + * @c Alloc::is_always_equal if that type exists, + * otherwise @c is_empty::type + */ + using is_always_equal + = typename __detected_or_t, __equal, _Alloc>::type; + + template + using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; + template + using rebind_traits = allocator_traits>; + + private: + template + static constexpr auto + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) + -> decltype(__a.allocate(__n, __hint)) + { return __a.allocate(__n, __hint); } + + template + static constexpr pointer + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) + { return __a.allocate(__n); } + + template + struct __construct_helper + { + template()->construct( + std::declval<_Tp*>(), std::declval<_Args>()...))> + static true_type __test(int); + + template + static false_type __test(...); + + using type = decltype(__test<_Alloc>(0)); + }; + + template + using __has_construct + = typename __construct_helper<_Tp, _Args...>::type; + + template + static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>> + _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + template + static _GLIBCXX14_CONSTEXPR + _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, + is_constructible<_Tp, _Args...>>> + _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value) + { +#if __cplusplus <= 201703L + ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + template + static _GLIBCXX14_CONSTEXPR auto + _S_destroy(_Alloc2& __a, _Tp* __p, int) + noexcept(noexcept(__a.destroy(__p))) + -> decltype(__a.destroy(__p)) + { __a.destroy(__p); } + + template + static _GLIBCXX14_CONSTEXPR void + _S_destroy(_Alloc2&, _Tp* __p, ...) + noexcept(std::is_nothrow_destructible<_Tp>::value) + { std::_Destroy(__p); } + + template + static constexpr auto + _S_max_size(_Alloc2& __a, int) + -> decltype(__a.max_size()) + { return __a.max_size(); } + + template + static constexpr size_type + _S_max_size(_Alloc2&, ...) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2466. allocator_traits::max_size() default behavior is incorrect + return __gnu_cxx::__numeric_traits::__max + / sizeof(value_type); + } + + template + static constexpr auto + _S_select(_Alloc2& __a, int) + -> decltype(__a.select_on_container_copy_construction()) + { return __a.select_on_container_copy_construction(); } + + template + static constexpr _Alloc2 + _S_select(_Alloc2& __a, ...) + { return __a; } + + public: + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) if that expression is + * well-formed, otherwise returns @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) + { return _S_allocate(__a, __n, __hint, 0); } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static _GLIBCXX20_CONSTEXPR void + deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type `_Tp` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for Tp + * @param __args Constructor arguments. + * + * Calls __a.construct(__p, std::forward(__args)...) + * if that expression is well-formed, otherwise uses placement-new + * to construct an object of type @a _Tp at location @a __p from the + * arguments @a __args... + */ + template + static _GLIBCXX20_CONSTEXPR auto + construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(_S_construct(__a, __p, + std::forward<_Args>(__args)...))) + -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) + { _S_construct(__a, __p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type @a _Tp + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p) if that expression is well-formed, + * otherwise calls @c __p->~_Tp() + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(_Alloc& __a, _Tp* __p) + noexcept(noexcept(_S_destroy(__a, __p, 0))) + { _S_destroy(__a, __p, 0); } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() or @c numeric_limits::max() + * + * Returns @c __a.max_size() if that expression is well-formed, + * otherwise returns @c numeric_limits::max() + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const _Alloc& __a) noexcept + { return _S_max_size(__a, 0); } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs.select_on_container_copy_construction() or @a __rhs + * + * Returns @c __rhs.select_on_container_copy_construction() if that + * expression is well-formed, otherwise returns @a __rhs + */ + static _GLIBCXX20_CONSTEXPR _Alloc + select_on_container_copy_construction(const _Alloc& __rhs) + { return _S_select(__rhs, 0); } + }; + +#if _GLIBCXX_HOSTED + /// Partial specialization for std::allocator. + template + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator<_Tp>; + + /// The allocated type + using value_type = _Tp; + + /// The allocator's pointer type. + using pointer = _Tp*; + + /// The allocator's const pointer type. + using const_pointer = const _Tp*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + [[__nodiscard__,__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) + */ + [[__nodiscard__,__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n, + [[maybe_unused]] const_void_pointer __hint) + { +#if __cplusplus <= 201703L + return __a.allocate(__n, __hint); +#else + return __a.allocate(__n); +#endif + } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + construct(allocator_type& __a __attribute__((__unused__)), _Up* __p, + _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { +#if __cplusplus <= 201703L + __a.construct(__p, std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + /** + * @brief Destroy an object of type @a _Up + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p). + */ + template + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { +#if __cplusplus <= 201703L + __a.destroy(__p); +#else + std::destroy_at(__p); +#endif + } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() + */ + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR size_type + max_size(const allocator_type& __a __attribute__((__unused__))) noexcept + { +#if __cplusplus <= 201703L + return __a.max_size(); +#else + return size_t(-1) / sizeof(value_type); +#endif + } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs + */ + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + + /// Explicit specialization for std::allocator. + template<> + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator; + + /// The allocated type + using value_type = void; + + /// The allocator's pointer type. + using pointer = void*; + + /// The allocator's const pointer type. + using const_pointer = const void*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /// allocate is ill-formed for allocator + static void* + allocate(allocator_type&, size_type, const void* = nullptr) = delete; + + /// deallocate is ill-formed for allocator + static void + deallocate(allocator_type&, void*, size_type) = delete; + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + construct(allocator_type&, _Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { std::_Construct(__p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Invokes the destructor for `*__p`. + */ + template + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type&, _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { std::_Destroy(__p); } + + /// max_size is ill-formed for allocator + static size_type + max_size(const allocator_type&) = delete; + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return `__rhs` + */ + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; +#endif + + /// @cond undocumented +#if __cplusplus < 201703L + template + [[__gnu__::__always_inline__]] + inline void + __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) + { __one = __two; } + + template + [[__gnu__::__always_inline__]] + inline void + __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) + { } +#endif + + template + [[__gnu__::__always_inline__]] + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_copy(_Alloc& __one, const _Alloc& __two) + { + using __traits = allocator_traits<_Alloc>; + using __pocca = + typename __traits::propagate_on_container_copy_assignment::type; +#if __cplusplus >= 201703L + if constexpr (__pocca::value) + __one = __two; +#else + __do_alloc_on_copy(__one, __two, __pocca()); +#endif + } + + template + [[__gnu__::__always_inline__]] + constexpr _Alloc + __alloc_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __traits; + return __traits::select_on_container_copy_construction(__a); + } + +#if __cplusplus < 201703L + template + [[__gnu__::__always_inline__]] + inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) + { __one = std::move(__two); } + + template + [[__gnu__::__always_inline__]] + inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + [[__gnu__::__always_inline__]] + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_move(_Alloc& __one, _Alloc& __two) + { + using __traits = allocator_traits<_Alloc>; + using __pocma + = typename __traits::propagate_on_container_move_assignment::type; +#if __cplusplus >= 201703L + if constexpr (__pocma::value) + __one = std::move(__two); +#else + __do_alloc_on_move(__one, __two, __pocma()); +#endif + } + +#if __cplusplus < 201703L + template + [[__gnu__::__always_inline__]] + inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) + { + using std::swap; + swap(__one, __two); + } + + template + [[__gnu__::__always_inline__]] + inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + [[__gnu__::__always_inline__]] + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_swap(_Alloc& __one, _Alloc& __two) + { + using __traits = allocator_traits<_Alloc>; + using __pocs = typename __traits::propagate_on_container_swap::type; +#if __cplusplus >= 201703L + if constexpr (__pocs::value) + { + using std::swap; + swap(__one, __two); + } +#else + __do_alloc_on_swap(__one, __two, __pocs()); +#endif + } + + template, + typename = void> + struct __is_alloc_insertable_impl + : false_type + { }; + + template + struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT, + __void_t::construct( + std::declval<_Alloc&>(), std::declval<_ValueT*>(), + std::declval<_Tp>()))>> + : true_type + { }; + + // true if _Alloc::value_type is CopyInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_copy_insertable + : __is_alloc_insertable_impl<_Alloc, + typename _Alloc::value_type const&>::type + { }; + +#if _GLIBCXX_HOSTED + // std::allocator<_Tp> just requires CopyConstructible + template + struct __is_copy_insertable> + : is_copy_constructible<_Tp> + { }; +#endif + + // true if _Alloc::value_type is MoveInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_move_insertable + : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type + { }; + +#if _GLIBCXX_HOSTED + // std::allocator<_Tp> just requires MoveConstructible + template + struct __is_move_insertable> + : is_move_constructible<_Tp> + { }; +#endif + + // Trait to detect Allocator-like types. + template + struct __is_allocator : false_type { }; + + template + struct __is_allocator<_Alloc, + __void_t().allocate(size_t{}))>> + : true_type { }; + + template + using _RequireAllocator + = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; + + template + using _RequireNotAllocator + = typename enable_if::value, _Alloc>::type; + +#if __cpp_concepts >= 201907L + template + concept __allocator_like = requires (_Alloc& __a) { + typename _Alloc::value_type; + __a.deallocate(__a.allocate(1u), 1u); + }; +#endif + /// @endcond +#endif // C++11 + + /// @cond undocumented + + // To implement Option 3 of DR 431. + template + struct __alloc_swap + { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } }; + + template + struct __alloc_swap<_Alloc, false> + { + static void + _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT + { + // Precondition: swappable allocators. + if (__one != __two) + swap(__one, __two); + } + }; + +#if __cplusplus >= 201103L + template, + is_nothrow_move_constructible>::value> + struct __shrink_to_fit_aux + { static bool _S_do_it(_Tp&) noexcept { return false; } }; + + template + struct __shrink_to_fit_aux<_Tp, true> + { + _GLIBCXX20_CONSTEXPR + static bool + _S_do_it(_Tp& __c) noexcept + { +#if __cpp_exceptions + try + { + _Tp(__make_move_if_noexcept_iterator(__c.begin()), + __make_move_if_noexcept_iterator(__c.end()), + __c.get_allocator()).swap(__c); + return true; + } + catch(...) + { return false; } +#else + return false; +#endif + } + }; +#endif + + /** + * Destroy a range of objects using the supplied allocator. For + * non-default allocators we do not optimize away invocation of + * destroy() even if _Tp has a trivial destructor. + */ + + template + _GLIBCXX20_CONSTEXPR + void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + _Allocator& __alloc) + { + for (; __first != __last; ++__first) +#if __cplusplus < 201103L + __alloc.destroy(std::__addressof(*__first)); +#else + allocator_traits<_Allocator>::destroy(__alloc, + std::__addressof(*__first)); +#endif + } + +#if _GLIBCXX_HOSTED + template + __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR + inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + allocator<_Tp>&) + { + std::_Destroy(__first, __last); + } +#endif + /// @endcond + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // _ALLOC_TRAITS_H diff --git a/template/sysroot/include/bits/allocator.h b/template/sysroot/include/bits/allocator.h new file mode 100644 index 0000000..9e75b37 --- /dev/null +++ b/template/sysroot/include/bits/allocator.h @@ -0,0 +1,295 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATOR_H +#define _ALLOCATOR_H 1 + +#include // Define the base class to std::allocator. +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + // Since C++20 the primary template should be used for allocator, + // but then it would have a non-trivial default ctor and dtor for C++20, + // but trivial for C++98-17, which would be an ABI incompatibility between + // different standard dialects. So C++20 still uses the allocator + // explicit specialization, with the historical ABI properties, but with + // the same members that are present in the primary template. + + /** std::allocator specialization. + * + * @headerfile memory + */ + template<> + class allocator + { + public: + typedef void value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + +#if __cplusplus <= 201703L + // These were removed for C++20, allocator_traits does the right thing. + typedef void* pointer; + typedef const void* const_pointer; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + using propagate_on_container_move_assignment = true_type; + + using is_always_equal + _GLIBCXX20_DEPRECATED_SUGGEST("std::allocator_traits::is_always_equal") + = true_type; + +#if __cplusplus >= 202002L + // As noted above, these members are present for C++20 to provide the + // same API as the primary template, but still trivial as in pre-C++20. + allocator() = default; + ~allocator() = default; + + template + __attribute__((__always_inline__)) + constexpr + allocator(const allocator<_Up>&) noexcept { } + + // No allocate member because it's ill-formed by LWG 3307. + // No deallocate member because it would be undefined to call it + // with any pointer which wasn't obtained from allocate. +#endif // C++20 +#endif // C++11 + }; + + /** + * @brief The @a standard allocator, as per C++03 [20.4.1]. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator + * for further details. + * + * @tparam _Tp Type of allocated object. + * + * @headerfile memory + */ + template + class allocator : public __allocator_base<_Tp> + { + public: + typedef _Tp value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + +#if __cplusplus <= 201703L + // These were removed for C++20. + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + using propagate_on_container_move_assignment = true_type; + + using is_always_equal + _GLIBCXX20_DEPRECATED_SUGGEST("std::allocator_traits::is_always_equal") + = true_type; +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3035. std::allocator's constructors should be constexpr + __attribute__((__always_inline__)) + _GLIBCXX20_CONSTEXPR + allocator() _GLIBCXX_NOTHROW { } + + __attribute__((__always_inline__)) + _GLIBCXX20_CONSTEXPR + allocator(const allocator& __a) _GLIBCXX_NOTHROW + : __allocator_base<_Tp>(__a) { } + +#if __cplusplus >= 201103L + // Avoid implicit deprecation. + allocator& operator=(const allocator&) = default; +#endif + + template + __attribute__((__always_inline__)) + _GLIBCXX20_CONSTEXPR + allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { } + + __attribute__((__always_inline__)) +#if __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~allocator() _GLIBCXX_NOTHROW { } + +#if __cplusplus > 201703L + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + allocate(size_t __n) + { + if (std::__is_constant_evaluated()) + { + if (__builtin_mul_overflow(__n, sizeof(_Tp), &__n)) + std::__throw_bad_array_new_length(); + return static_cast<_Tp*>(::operator new(__n)); + } + + return __allocator_base<_Tp>::allocate(__n, 0); + } + + [[__gnu__::__always_inline__]] + constexpr void + deallocate(_Tp* __p, size_t __n) + { + if (std::__is_constant_evaluated()) + { + ::operator delete(__p); + return; + } + __allocator_base<_Tp>::deallocate(__p, __n); + } +#endif // C++20 + + friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR + bool + operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR + bool + operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return false; } +#endif + + // Inherit everything else. + }; + + /** Equality comparison for std::allocator objects + * + * @return true, for all std::allocator objects. + * @relates std::allocator + */ + template + __attribute__((__always_inline__)) + inline _GLIBCXX20_CONSTEXPR bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + __attribute__((__always_inline__)) + inline _GLIBCXX20_CONSTEXPR bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + /// @cond undocumented + + // Invalid allocator partial specializations. + // allocator_traits::rebind_alloc can be used to form a valid allocator type. + template + class allocator + { + public: + typedef _Tp value_type; + allocator() { } + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + allocator() { } + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + allocator() { } + template allocator(const allocator<_Up>&) { } + }; + /// @endcond + + /// @} group allocator + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. +#if _GLIBCXX_EXTERN_TEMPLATE + extern template class allocator; + extern template class allocator; +#endif + + // Undefine. +#undef __allocator_base + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/template/sysroot/include/bits/atomic_base.h b/template/sysroot/include/bits/atomic_base.h new file mode 100644 index 0000000..dd36030 --- /dev/null +++ b/template/sysroot/include/bits/atomic_base.h @@ -0,0 +1,2068 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_base.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_BASE_H +#define _GLIBCXX_ATOMIC_BASE_H 1 + +#pragma GCC system_header + +#include +#include // For placement new +#include +#include +#include + +#if __cplusplus > 201703L && _GLIBCXX_HOSTED +#include +#endif + +#ifndef _GLIBCXX_ALWAYS_INLINE +#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup atomics Atomics + * + * Components for performing atomic operations. + * @{ + */ + + /// Enumeration for memory_order +#if __cplusplus > 201703L + enum class memory_order : int + { + relaxed, + consume, + acquire, + release, + acq_rel, + seq_cst + }; + + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; +#else + typedef enum memory_order + { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst + } memory_order; +#endif + + /// @cond undocumented + enum __memory_order_modifier + { + __memory_order_mask = 0x0ffff, + __memory_order_modifier_mask = 0xffff0000, + __memory_order_hle_acquire = 0x10000, + __memory_order_hle_release = 0x20000 + }; + /// @endcond + + constexpr memory_order + operator|(memory_order __m, __memory_order_modifier __mod) noexcept + { + return memory_order(int(__m) | int(__mod)); + } + + constexpr memory_order + operator&(memory_order __m, __memory_order_modifier __mod) noexcept + { + return memory_order(int(__m) & int(__mod)); + } + + /// @cond undocumented + + // Drop release ordering as per [atomics.types.operations.req]/21 + constexpr memory_order + __cmpexch_failure_order2(memory_order __m) noexcept + { + return __m == memory_order_acq_rel ? memory_order_acquire + : __m == memory_order_release ? memory_order_relaxed : __m; + } + + constexpr memory_order + __cmpexch_failure_order(memory_order __m) noexcept + { + return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) + | __memory_order_modifier(__m & __memory_order_modifier_mask)); + } + + constexpr bool + __is_valid_cmpexch_failure_order(memory_order __m) noexcept + { + return (__m & __memory_order_mask) != memory_order_release + && (__m & __memory_order_mask) != memory_order_acq_rel; + } + + // Base types for atomics. + template + struct __atomic_base; + + /// @endcond + + _GLIBCXX_ALWAYS_INLINE void + atomic_thread_fence(memory_order __m) noexcept + { __atomic_thread_fence(int(__m)); } + + _GLIBCXX_ALWAYS_INLINE void + atomic_signal_fence(memory_order __m) noexcept + { __atomic_signal_fence(int(__m)); } + + /// kill_dependency + template + inline _Tp + kill_dependency(_Tp __y) noexcept + { + _Tp __ret(__y); + return __ret; + } + +/// @cond undocumented +#if __glibcxx_atomic_value_initialization +# define _GLIBCXX20_INIT(I) = I +#else +# define _GLIBCXX20_INIT(I) +#endif +/// @endcond + +#define ATOMIC_VAR_INIT(_VI) { _VI } + + template + struct atomic; + + template + struct atomic<_Tp*>; + + /* The target's "set" value for test-and-set may not be exactly 1. */ +#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 + typedef bool __atomic_flag_data_type; +#else + typedef unsigned char __atomic_flag_data_type; +#endif + + /// @cond undocumented + + /* + * Base type for atomic_flag. + * + * Base type is POD with data, allowing atomic_flag to derive from + * it and meet the standard layout type requirement. In addition to + * compatibility with a C interface, this allows different + * implementations of atomic_flag to use the same atomic operation + * functions, via a standard conversion to the __atomic_flag_base + * argument. + */ + _GLIBCXX_BEGIN_EXTERN_C + + struct __atomic_flag_base + { + __atomic_flag_data_type _M_i _GLIBCXX20_INIT({}); + }; + + _GLIBCXX_END_EXTERN_C + + /// @endcond + +#define ATOMIC_FLAG_INIT { 0 } + + /// atomic_flag + struct atomic_flag : public __atomic_flag_base + { + atomic_flag() noexcept = default; + ~atomic_flag() noexcept = default; + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + + // Conversion to ATOMIC_FLAG_INIT. + constexpr atomic_flag(bool __i) noexcept + : __atomic_flag_base{ _S_init(__i) } + { } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + +#ifdef __glibcxx_atomic_flag_test // C++ >= 20 + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } + + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } +#endif + +#if __glibcxx_atomic_wait // C++ >= 20 && (linux_futex || gthread) + _GLIBCXX_ALWAYS_INLINE void + wait(bool __old, + memory_order __m = memory_order_seq_cst) const noexcept + { + const __atomic_flag_data_type __v + = __old ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; + + std::__atomic_wait_address_v(&_M_i, __v, + [__m, this] { return __atomic_load_n(&_M_i, int(__m)); }); + } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() noexcept + { std::__atomic_notify_address(&_M_i, false); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() noexcept + { std::__atomic_notify_address(&_M_i, true); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + private: + static constexpr __atomic_flag_data_type + _S_init(bool __i) + { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } + }; + + /// @cond undocumented + + /// Base class for atomic integrals. + // + // For each of the integral types, define atomic_[integral type] struct + // + // atomic_bool bool + // atomic_char char + // atomic_schar signed char + // atomic_uchar unsigned char + // atomic_short short + // atomic_ushort unsigned short + // atomic_int int + // atomic_uint unsigned int + // atomic_long long + // atomic_ulong unsigned long + // atomic_llong long long + // atomic_ullong unsigned long long + // atomic_char8_t char8_t + // atomic_char16_t char16_t + // atomic_char32_t char32_t + // atomic_wchar_t wchar_t + // + // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or + // 8 bytes, since that is what GCC built-in functions for atomic + // memory access expect. + template + struct __atomic_base + { + using value_type = _ITp; + using difference_type = value_type; + + private: + typedef _ITp __int_type; + + static constexpr int _S_alignment = + sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); + + alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0); + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __int_type convertible to _M_i. + constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } + + operator __int_type() const noexcept + { return load(); } + + operator __int_type() const volatile noexcept + { return load(); } + + __int_type + operator=(__int_type __i) noexcept + { + store(__i); + return __i; + } + + __int_type + operator=(__int_type __i) volatile noexcept + { + store(__i); + return __i; + } + + __int_type + operator++(int) noexcept + { return fetch_add(1); } + + __int_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __int_type + operator--(int) noexcept + { return fetch_sub(1); } + + __int_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __int_type + operator++() noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) volatile noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) volatile noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) volatile noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) volatile noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) volatile noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(__int_type __old, + memory_order __m = memory_order_seq_cst) const noexcept + { + std::__atomic_wait_address_v(&_M_i, __old, + [__m, this] { return this->load(__m); }); + } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() noexcept + { std::__atomic_notify_address(&_M_i, false); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() noexcept + { std::__atomic_notify_address(&_M_i, true); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + }; + + + /// Partial specialization for pointer types. + template + struct __atomic_base<_PTp*> + { + private: + typedef _PTp* __pointer_type; + + __pointer_type _M_p _GLIBCXX20_INIT(nullptr); + + // Factored out to facilitate explicit specialization. + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } + + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __pointer_type convertible to _M_p. + constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } + + operator __pointer_type() const noexcept + { return load(); } + + operator __pointer_type() const volatile noexcept + { return load(); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator++(int) noexcept + { return fetch_add(1); } + + __pointer_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __pointer_type + operator--(int) noexcept + { return fetch_sub(1); } + + __pointer_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __pointer_type + operator++() noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b __attribute__ ((__unused__)) + = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2)); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(__pointer_type __old, + memory_order __m = memory_order_seq_cst) const noexcept + { + std::__atomic_wait_address_v(&_M_p, __old, + [__m, this] + { return this->load(__m); }); + } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { std::__atomic_notify_address(&_M_p, false); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { std::__atomic_notify_address(&_M_p, true); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + }; + + namespace __atomic_impl + { + // Implementation details of atomic padding handling + + template + constexpr bool + __maybe_has_padding() + { +#if ! __has_builtin(__builtin_clear_padding) + return false; +#elif __has_builtin(__has_unique_object_representations) + return !__has_unique_object_representations(_Tp) + && !is_same<_Tp, float>::value && !is_same<_Tp, double>::value; +#else + return true; +#endif + } + + template + _GLIBCXX_ALWAYS_INLINE _Tp* + __clear_padding(_Tp& __val) noexcept + { + auto* __ptr = std::__addressof(__val); +#if __has_builtin(__builtin_clear_padding) + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>()) + __builtin_clear_padding(__ptr); +#endif + return __ptr; + } + + // Remove volatile and create a non-deduced context for value arguments. + template + using _Val = typename remove_volatile<_Tp>::type; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" + + template + _GLIBCXX_ALWAYS_INLINE bool + __compare_exchange(_Tp& __val, _Val<_Tp>& __e, _Val<_Tp>& __i, + bool __is_weak, + memory_order __s, memory_order __f) noexcept + { + __glibcxx_assert(__is_valid_cmpexch_failure_order(__f)); + + using _Vp = _Val<_Tp>; + _Tp* const __pval = std::__addressof(__val); + + if constexpr (!__atomic_impl::__maybe_has_padding<_Vp>()) + { + return __atomic_compare_exchange(__pval, std::__addressof(__e), + std::__addressof(__i), __is_weak, + int(__s), int(__f)); + } + else if constexpr (!_AtomicRef) // std::atomic + { + // Clear padding of the value we want to set: + _Vp* const __pi = __atomic_impl::__clear_padding(__i); + // Only allowed to modify __e on failure, so make a copy: + _Vp __exp = __e; + // Clear padding of the expected value: + _Vp* const __pexp = __atomic_impl::__clear_padding(__exp); + + // For std::atomic we know that the contained value will already + // have zeroed padding, so trivial memcmp semantics are OK. + if (__atomic_compare_exchange(__pval, __pexp, __pi, + __is_weak, int(__s), int(__f))) + return true; + // Value bits must be different, copy from __exp back to __e: + __builtin_memcpy(std::__addressof(__e), __pexp, sizeof(_Vp)); + return false; + } + else // std::atomic_ref where T has padding bits. + { + // Clear padding of the value we want to set: + _Vp* const __pi = __atomic_impl::__clear_padding(__i); + + // Only allowed to modify __e on failure, so make a copy: + _Vp __exp = __e; + // Optimistically assume that a previous store had zeroed padding + // so that zeroing it in the expected value will match first time. + _Vp* const __pexp = __atomic_impl::__clear_padding(__exp); + + // compare_exchange is specified to compare value representations. + // Need to check whether a failure is 'real' or just due to + // differences in padding bits. This loop should run no more than + // three times, because the worst case scenario is: + // First CAS fails because the actual value has non-zero padding. + // Second CAS fails because another thread stored the same value, + // but now with padding cleared. Third CAS succeeds. + // We will never need to loop a fourth time, because any value + // written by another thread (whether via store, exchange or + // compare_exchange) will have had its padding cleared. + while (true) + { + // Copy of the expected value so we can clear its padding. + _Vp __orig = __exp; + + if (__atomic_compare_exchange(__pval, __pexp, __pi, + __is_weak, int(__s), int(__f))) + return true; + + // Copy of the actual value so we can clear its padding. + _Vp __curr = __exp; + + // Compare value representations (i.e. ignoring padding). + if (__builtin_memcmp(__atomic_impl::__clear_padding(__orig), + __atomic_impl::__clear_padding(__curr), + sizeof(_Vp))) + { + // Value representations compare unequal, real failure. + __builtin_memcpy(std::__addressof(__e), __pexp, + sizeof(_Vp)); + return false; + } + } + } + } +#pragma GCC diagnostic pop + } // namespace __atomic_impl + +#if __cplusplus > 201703L + // Implementation details of atomic_ref and atomic. + namespace __atomic_impl + { + // Like _Val above, but for difference_type arguments. + template + using _Diff = __conditional_t, ptrdiff_t, _Val<_Tp>>; + + template + _GLIBCXX_ALWAYS_INLINE bool + is_lock_free() noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(_Size, reinterpret_cast(-_Align)); + } + + template + _GLIBCXX_ALWAYS_INLINE void + store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept + { + __atomic_store(__ptr, __atomic_impl::__clear_padding(__t), int(__m)); + } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + load(const _Tp* __ptr, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_load(__ptr, __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_exchange(__ptr, __atomic_impl::__clear_padding(__desired), + __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure, + bool __check_padding = false) noexcept + { + return __atomic_impl::__compare_exchange<_AtomicRef>( + *__ptr, __expected, __desired, true, __success, __failure); + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure, + bool __ignore_padding = false) noexcept + { + return __atomic_impl::__compare_exchange<_AtomicRef>( + *__ptr, __expected, __desired, false, __success, __failure); + } + +#if __glibcxx_atomic_wait + template + _GLIBCXX_ALWAYS_INLINE void + wait(const _Tp* __ptr, _Val<_Tp> __old, + memory_order __m = memory_order_seq_cst) noexcept + { + std::__atomic_wait_address_v(__ptr, __old, + [__ptr, __m]() { return __atomic_impl::load(__ptr, __m); }); + } + + // TODO add const volatile overload + + template + _GLIBCXX_ALWAYS_INLINE void + notify_one(const _Tp* __ptr) noexcept + { std::__atomic_notify_address(__ptr, false); } + + // TODO add const volatile overload + + template + _GLIBCXX_ALWAYS_INLINE void + notify_all(const _Tp* __ptr) noexcept + { std::__atomic_notify_address(__ptr, true); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_add(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_sub(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_and(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_or(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_xor(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _Tp + __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval + __i; + return __oldval; + } + + template + _Tp + __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval - __i; + return __oldval; + } + + template + _Tp + __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval + __i; + return __newval; + } + + template + _Tp + __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval - __i; + return __newval; + } + } // namespace __atomic_impl + + // base class for atomic + template + struct __atomic_float + { + static_assert(is_floating_point_v<_Fp>); + + static constexpr size_t _S_alignment = __alignof__(_Fp); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + __atomic_float() = default; + + constexpr + __atomic_float(_Fp __t) : _M_fp(__t) + { __atomic_impl::__clear_padding(_M_fp); } + + __atomic_float(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) volatile = delete; + + _Fp + operator=(_Fp __t) volatile noexcept + { + this->store(__t); + return __t; + } + + _Fp + operator=(_Fp __t) noexcept + { + this->store(__t); + return __t; + } + + bool + is_lock_free() const volatile noexcept + { return __atomic_impl::is_lock_free(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + operator _Fp() const volatile noexcept { return this->load(); } + operator _Fp() const noexcept { return this->load(); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::wait(&_M_fp, __old, __m); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { __atomic_impl::notify_one(&_M_fp); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { __atomic_impl::notify_all(&_M_fp); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + operator+=(value_type __i) noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator+=(value_type __i) volatile noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) volatile noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + private: + alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0); + }; +#undef _GLIBCXX20_INIT + + template, bool = is_floating_point_v<_Tp>> + struct __atomic_ref; + + // base class for non-integral, non-floating-point, non-pointer types + template + struct __atomic_ref<_Tp, false, false> + { + static_assert(is_trivially_copyable_v<_Tp>); + + // 1/2/4/8/16-byte types must be aligned to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + public: + using value_type = _Tp; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) + const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::wait(_M_ptr, __old, __m); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { __atomic_impl::notify_one(_M_ptr); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { __atomic_impl::notify_all(_M_ptr); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp, true, false> + { + static_assert(is_integral_v<_Tp>); + + public: + using value_type = _Tp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::wait(_M_ptr, __old, __m); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { __atomic_impl::notify_one(_M_ptr); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { __atomic_impl::notify_all(_M_ptr); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } + + value_type + fetch_and(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } + + value_type + fetch_or(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } + + value_type + fetch_xor(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator++(int) const noexcept + { return fetch_add(1); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } + + value_type + operator--() const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, __i); } + + value_type + operator&=(value_type __i) const noexcept + { return __atomic_impl::__and_fetch(_M_ptr, __i); } + + value_type + operator|=(value_type __i) const noexcept + { return __atomic_impl::__or_fetch(_M_ptr, __i); } + + value_type + operator^=(value_type __i) const noexcept + { return __atomic_impl::__xor_fetch(_M_ptr, __i); } + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Fp, false, true> + { + static_assert(is_floating_point_v<_Fp>); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + static constexpr size_t required_alignment = __alignof__(_Fp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Fp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Fp + operator=(_Fp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Fp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::wait(_M_ptr, __old, __m); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { __atomic_impl::notify_one(_M_ptr); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { __atomic_impl::notify_all(_M_ptr); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } + + private: + _Fp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp*, false, false> + { + public: + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; + + static constexpr size_t required_alignment = __alignof__(_Tp*); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp* + operator=(_Tp* __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp*() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp* + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp* + exchange(_Tp* __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong( + _M_ptr, __expected, __desired, __success, __failure); + } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + +#if __glibcxx_atomic_wait + _GLIBCXX_ALWAYS_INLINE void + wait(_Tp* __old, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::wait(_M_ptr, __old, __m); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_one() const noexcept + { __atomic_impl::notify_one(_M_ptr); } + + // TODO add const volatile overload + + _GLIBCXX_ALWAYS_INLINE void + notify_all() const noexcept + { __atomic_impl::notify_all(_M_ptr); } + + // TODO add const volatile overload +#endif // __glibcxx_atomic_wait + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_add(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_sub(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } + + value_type + operator++(int) const noexcept + { return fetch_add(1); } + + value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator--() const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator+=(difference_type __d) const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); + } + + value_type + operator-=(difference_type __d) const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); + } + + private: + static constexpr ptrdiff_t + _S_type_size(ptrdiff_t __d) noexcept + { + static_assert(is_object_v<_Tp>); + return __d * sizeof(_Tp); + } + + _Tp** _M_ptr; + }; +#endif // C++2a + + /// @endcond + + /// @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/template/sysroot/include/bits/atomic_lockfree_defines.h b/template/sysroot/include/bits/atomic_lockfree_defines.h new file mode 100644 index 0000000..978aedb --- /dev/null +++ b/template/sysroot/include/bits/atomic_lockfree_defines.h @@ -0,0 +1,66 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_lockfree_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H +#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1 + +#pragma GCC system_header + +/** + * @addtogroup atomics + * @{ + */ + +/** + * Lock-free property. + * + * 0 indicates that the types are never lock-free. + * 1 indicates that the types are sometimes lock-free. + * 2 indicates that the types are always lock-free. + */ + +#if __cplusplus >= 201103L +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#ifdef _GLIBCXX_USE_CHAR8_T +#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +/// @} group atomics + +#endif diff --git a/template/sysroot/include/bits/atomic_word.h b/template/sysroot/include/bits/atomic_word.h new file mode 100644 index 0000000..ab34fe9 --- /dev/null +++ b/template/sysroot/include/bits/atomic_word.h @@ -0,0 +1,40 @@ +// Low-level type for atomic operations -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file atomic_word.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_ATOMIC_WORD_H +#define _GLIBCXX_ATOMIC_WORD_H 1 + +typedef int _Atomic_word; + + +// This is a memory order acquire fence. +#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) +// This is a memory order release fence. +#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) + +#endif diff --git a/template/sysroot/include/bits/basic_file.h b/template/sysroot/include/bits/basic_file.h new file mode 100644 index 0000000..baaa513 --- /dev/null +++ b/template/sysroot/include/bits/basic_file.h @@ -0,0 +1,148 @@ +// Wrapper of C-language FILE struct -*- C++ -*- + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 27.8 File-based streams +// + +/** @file bits/basic_file.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ios} + */ + +#ifndef _GLIBCXX_BASIC_FILE_STDIO_H +#define _GLIBCXX_BASIC_FILE_STDIO_H 1 + +#pragma GCC system_header + +#include +#include // for __c_lock and __c_file +#include // for swap +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Generic declaration. + template + class __basic_file; + + // Specialization. + template<> + class __basic_file + { + // Underlying data source/sink. + __c_file* _M_cfile; + + // True iff we opened _M_cfile, and thus must close it ourselves. + bool _M_cfile_created; + + public: + __basic_file(__c_lock* __lock = 0) throw (); + +#if __cplusplus >= 201103L + __basic_file(__basic_file&& __rv, __c_lock* = 0) noexcept + : _M_cfile(__rv._M_cfile), _M_cfile_created(__rv._M_cfile_created) + { + __rv._M_cfile = nullptr; + __rv._M_cfile_created = false; + } + + __basic_file& operator=(const __basic_file&) = delete; + __basic_file& operator=(__basic_file&&) = delete; + + void + swap(__basic_file& __f) noexcept + { + std::swap(_M_cfile, __f._M_cfile); + std::swap(_M_cfile_created, __f._M_cfile_created); + } +#endif + + __basic_file* + open(const char* __name, ios_base::openmode __mode, int __prot = 0664); + +#if _GLIBCXX_HAVE__WFOPEN && _GLIBCXX_USE_WCHAR_T + __basic_file* + open(const wchar_t* __name, ios_base::openmode __mode); +#endif + + __basic_file* + sys_open(__c_file* __file, ios_base::openmode); + + __basic_file* + sys_open(int __fd, ios_base::openmode __mode) throw (); + + __basic_file* + close(); + + _GLIBCXX_PURE bool + is_open() const throw (); + + _GLIBCXX_PURE int + fd() throw (); + + _GLIBCXX_PURE __c_file* + file() throw (); + + ~__basic_file(); + + streamsize + xsputn(const char* __s, streamsize __n); + + streamsize + xsputn_2(const char* __s1, streamsize __n1, + const char* __s2, streamsize __n2); + + streamsize + xsgetn(char* __s, streamsize __n); + + streamoff + seekoff(streamoff __off, ios_base::seekdir __way) throw (); + + int + sync(); + + streamsize + showmanyc(); + +#if __cplusplus >= 201103L +#ifdef _GLIBCXX_USE_STDIO_PURE + using native_handle_type = __c_file*; // FILE* +#elif _GLIBCXX_USE__GET_OSFHANDLE + using native_handle_type = void*; // HANDLE +#else + using native_handle_type = int; // POSIX file descriptor +#endif + + native_handle_type + native_handle() const noexcept; +#endif + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/boost_concept_check.h b/template/sysroot/include/bits/boost_concept_check.h new file mode 100644 index 0000000..a042ae6 --- /dev/null +++ b/template/sysroot/include/bits/boost_concept_check.h @@ -0,0 +1,883 @@ +// -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// + +/** @file bits/boost_concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +// GCC Note: based on version 1.12.0 of the Boost library. + +#ifndef _BOOST_CONCEPT_CHECK_H +#define _BOOST_CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include +#include // for traits and tags + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + struct _Bit_iterator; + struct _Bit_const_iterator; +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace __gnu_debug +{ + template + class _Safe_iterator; +} + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" + +#define _IsUnused __attribute__ ((__unused__)) + +// When the C-C code is in use, we would like this function to do as little +// as possible at runtime, use as few resources as possible, and hopefully +// be elided out of existence... hmmm. +template +_GLIBCXX14_CONSTEXPR inline void __function_requires() +{ + void (_Concept::*__x)() _IsUnused = &_Concept::__constraints; +} + +// No definition: if this is referenced, there's a problem with +// the instantiating type not being one of the required integer types. +// Unfortunately, this results in a link-time error, not a compile-time error. +void __error_type_must_be_an_integer_type(); +void __error_type_must_be_an_unsigned_integer_type(); +void __error_type_must_be_a_signed_integer_type(); + +// ??? Should the "concept_checking*" structs begin with more than _ ? +#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \ + typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \ + template <_func##_type_var##_concept _Tp1> \ + struct _concept_checking##_type_var##_concept { }; \ + typedef _concept_checking##_type_var##_concept< \ + &_ns::_concept <_type_var>::__constraints> \ + _concept_checking_typedef##_type_var##_concept + +#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \ + template <_func##_type_var1##_type_var2##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_concept< \ + &_ns::_concept <_type_var1,_type_var2>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_concept + +#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept + +#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept + + +template +struct _Aux_require_same { }; + +template +struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; + + template + struct _SameTypeConcept + { + void __constraints() { + typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required; + } + }; + + template + struct _IntegerConcept { + void __constraints() { + __error_type_must_be_an_integer_type(); + } + }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints(){} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept + { void __constraints() {} }; + + template + struct _SignedIntegerConcept { + void __constraints() { + __error_type_must_be_a_signed_integer_type(); + } + }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints(){}}; + + template + struct _UnsignedIntegerConcept { + void __constraints() { + __error_type_must_be_an_unsigned_integer_type(); + } + }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + + //=========================================================================== + // Basic Concepts + + template + struct _DefaultConstructibleConcept + { + void __constraints() { + _Tp __a _IsUnused; // require default constructor + } + }; + + template + struct _AssignableConcept + { + void __constraints() { + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + __a = __b; // const required for argument to assignment + } + _Tp __a; + // possibly should be "Tp* a;" and then dereference "a" in constraint + // functions? present way would require a default ctor, i think... + }; + + template + struct _CopyConstructibleConcept + { + void __constraints() { + _Tp __a(__b); // require copy constructor + _Tp* __ptr _IsUnused = &__a; // require address of operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __a) { + _Tp __c _IsUnused(__a); // require const copy constructor + const _Tp* __ptr _IsUnused = &__a; // require const address of operator + } + _Tp __b; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + template + struct _SGIAssignableConcept + { + void __constraints() { + _Tp __b _IsUnused(__a); + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + _Tp __c _IsUnused(__b); + __a = __b; // const required for argument to assignment + } + _Tp __a; + }; + + template + struct _ConvertibleConcept + { + void __constraints() { + _To __y _IsUnused = __x; + } + _From __x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template + void __aux_require_boolean_expr(const _Tp& __t) { + bool __x _IsUnused = __t; + } + +// FIXME + template + struct _EqualityComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a == __b); + } + _Tp __a, __b; + }; + + template + struct _LessThanComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + } + _Tp __a, __b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template + struct _ComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + __aux_require_boolean_expr(__a > __b); + __aux_require_boolean_expr(__a <= __b); + __aux_require_boolean_expr(__a >= __b); + } + _Tp __a, __b; + }; + +#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + bool __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + +#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + _Ret __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept); + + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept); + +#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT +#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT + + //=========================================================================== + // Function Object Concepts + + template + struct _GeneratorConcept + { + void __constraints() { + const _Return& __r _IsUnused = __f();// require operator() member function + } + _Func __f; + }; + + + template + struct _GeneratorConcept<_Func,void> + { + void __constraints() { + __f(); // require operator() member function + } + _Func __f; + }; + + template + struct _UnaryFunctionConcept + { + void __constraints() { + __r = __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + _Return __r; + }; + + template + struct _UnaryFunctionConcept<_Func, void, _Arg> { + void __constraints() { + __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryFunctionConcept + { + void __constraints() { + __r = __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + _Return __r; + }; + + template + struct _BinaryFunctionConcept<_Func, void, _First, _Second> + { + void __constraints() { + __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + }; + + template + struct _UnaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__arg)); // require op() returning bool + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool + } + _Func __f; + _First __a; + _Second __b; + }; + + // use this when functor is used inside a container class like std::set + template + struct _Const_BinaryPredicateConcept { + void __constraints() { + __const_constraints(__f); + } + void __const_constraints(const _Func& __fun) { + __function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >(); + // operator() must be a const member function + __aux_require_boolean_expr(__fun(__a, __b)); + } + _Func __f; + _First __a; + _Second __b; + }; + + //=========================================================================== + // Iterator Concepts + + template + struct _TrivialIteratorConcept + { + void __constraints() { +// __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _AssignableConcept<_Tp> >(); + __function_requires< _EqualityComparableConcept<_Tp> >(); +// typedef typename std::iterator_traits<_Tp>::value_type _V; + (void)*__i; // require dereference operator + } + _Tp __i; + }; + + template + struct _Mutable_TrivialIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + *__i = *__j; // require dereference and assignment + } + _Tp __i, __j; + }; + + template + struct _InputIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + // require iterator_traits typedef's + typedef typename std::iterator_traits<_Tp>::difference_type _Diff; +// __function_requires< _SignedIntegerConcept<_Diff> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::pointer _Pt; + typedef typename std::iterator_traits<_Tp>::iterator_category _Cat; + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::input_iterator_tag> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + } + _Tp __i; + }; + + template + struct _OutputIteratorConcept + { + void __constraints() { + __function_requires< _AssignableConcept<_Tp> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + *__i++ = __val(); // require postincrement and assignment + } + _Tp __i; + // Use a function pointer here so no definition of the function needed. + // Just need something that returns a _ValueT (which might be a reference). + _ValueT (*__val)(); + }; + + template + struct _Is_vector_bool_iterator + { static const bool __value = false; }; + +#ifdef _GLIBCXX_DEBUG + namespace __cont = ::std::_GLIBCXX_STD_C; +#else + namespace __cont = ::std; +#endif + + // Trait to identify vector::iterator + template <> + struct _Is_vector_bool_iterator<__cont::_Bit_iterator> + { static const bool __value = true; }; + + // And for vector::const_iterator. + template <> + struct _Is_vector_bool_iterator<__cont::_Bit_const_iterator> + { static const bool __value = true; }; + + // And for __gnu_debug::vector iterators too. + template + struct _Is_vector_bool_iterator<__gnu_debug::_Safe_iterator<_It, _Seq, _Tag> > + : _Is_vector_bool_iterator<_It> { }; + + template ::__value> + struct _ForwardIteratorReferenceConcept + { + void __constraints() { +#if __cplusplus >= 201103L + typedef typename std::iterator_traits<_Tp>::reference _Ref; + static_assert(std::is_reference<_Ref>::value, + "reference type of a forward iterator must be a real reference"); +#endif + } + }; + + template ::__value> + struct _Mutable_ForwardIteratorReferenceConcept + { + void __constraints() { + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::value_type _Val; + __function_requires< _SameTypeConcept<_Ref, _Val&> >(); + } + }; + + // vector iterators are not real forward iterators, but we ignore that. + template + struct _ForwardIteratorReferenceConcept<_Tp, true> + { + void __constraints() { } + }; + + // vector iterators are not real forward iterators, but we ignore that. + template + struct _Mutable_ForwardIteratorReferenceConcept<_Tp, true> + { + void __constraints() { } + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + + template + struct _ForwardIteratorConcept + { + void __constraints() { + __function_requires< _InputIteratorConcept<_Tp> >(); + __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::forward_iterator_tag> >(); + __function_requires< _ForwardIteratorReferenceConcept<_Tp> >(); + _Tp& __j = ++__i; + const _Tp& __k = __i++; + typedef typename std::iterator_traits<_Tp>::reference _Ref; + _Ref __r = *__k; + _Ref __r2 = *__i++; + } + _Tp __i; + }; + + template + struct _Mutable_ForwardIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::value_type _Val; + __function_requires< _Mutable_ForwardIteratorReferenceConcept<_Tp> >(); + } + _Tp __i; + }; + + template + struct _BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::bidirectional_iterator_tag> >(); + _Tp& __j = --__i; // require predecrement operator + const _Tp& __k = __i--; // require postdecrement operator + typedef typename std::iterator_traits<_Tp>::reference _Ref; + _Ref __r = *__j--; + } + _Tp __i; + }; + + template + struct _Mutable_BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); + } + _Tp __i; + }; + + + template + struct _RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _ComparableConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::random_access_iterator_tag> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + + _Tp& __j = __i += __n; // require assignment addition operator + __i = __i + __n; __i = __n + __i; // require addition with difference type + _Tp& __k = __i -= __n; // require assignment subtraction op + __i = __i - __n; // require subtraction with + // difference type + __n = __i - __j; // require difference operator + _Ref __r = __i[__n]; // require element access operator + } + _Tp __a, __b; + _Tp __i, __j; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + template + struct _Mutable_RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _RandomAccessIteratorConcept<_Tp> >(); + __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); + } + _Tp __i; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + +#pragma GCC diagnostic pop + + //=========================================================================== + // Container Concepts + + template + struct _ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::difference_type _Difference_type; + typedef typename _Container::size_type _Size_type; + typedef typename _Container::const_reference _Const_reference; + typedef typename _Container::const_pointer _Const_pointer; + typedef typename _Container::const_iterator _Const_iterator; + + void __constraints() { + __function_requires< _InputIteratorConcept<_Const_iterator> >(); + __function_requires< _AssignableConcept<_Container> >(); + const _Container __c; + __i = __c.begin(); + __i = __c.end(); + __n = __c.size(); + __n = __c.max_size(); + __b = __c.empty(); + } + bool __b; + _Const_iterator __i; + _Size_type __n; + }; + + template + struct _Mutable_ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::reference _Reference; + typedef typename _Container::iterator _Iterator; + typedef typename _Container::pointer _Pointer; + + void __constraints() { + __function_requires< _ContainerConcept<_Container> >(); + __function_requires< _AssignableConcept<_Value_type> >(); + __function_requires< _InputIteratorConcept<_Iterator> >(); + + __i = __c.begin(); + __i = __c.end(); + __c.swap(__c2); + } + _Iterator __i; + _Container __c, __c2; + }; + + template + struct _ForwardContainerConcept + { + void __constraints() { + __function_requires< _ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::const_iterator _Const_iterator; + __function_requires< _ForwardIteratorConcept<_Const_iterator> >(); + } + }; + + template + struct _Mutable_ForwardContainerConcept + { + void __constraints() { + __function_requires< _ForwardContainerConcept<_ForwardContainer> >(); + __function_requires< _Mutable_ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::iterator _Iterator; + __function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >(); + } + }; + + template + struct _ReversibleContainerConcept + { + typedef typename _ReversibleContainer::const_iterator _Const_iterator; + typedef typename _ReversibleContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< _ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires< _BidirectionalIteratorConcept<_Const_iterator> >(); + __function_requires< + _BidirectionalIteratorConcept<_Const_reverse_iterator> >(); + + const _ReversibleContainer __c; + _Const_reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + }; + + template + struct _Mutable_ReversibleContainerConcept + { + typedef typename _ReversibleContainer::iterator _Iterator; + typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires<_ReversibleContainerConcept<_ReversibleContainer> >(); + __function_requires< + _Mutable_ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >(); + + _Reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + _ReversibleContainer __c; + }; + + template + struct _RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::const_reference _Const_reference; + typedef typename _RandomAccessContainer::const_iterator _Const_iterator; + typedef typename _RandomAccessContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< + _ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _RandomAccessIteratorConcept<_Const_iterator> >(); + __function_requires< + _RandomAccessIteratorConcept<_Const_reverse_iterator> >(); + + const _RandomAccessContainer __c; + _Const_reference __r _IsUnused = __c[__n]; + } + _Size_type __n; + }; + + template + struct _Mutable_RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::reference _Reference; + typedef typename _RandomAccessContainer::iterator _Iterator; + typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires< + _RandomAccessContainerConcept<_RandomAccessContainer> >(); + __function_requires< + _Mutable_ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >(); + + _Reference __r _IsUnused = __c[__i]; + } + _Size_type __i; + _RandomAccessContainer __c; + }; + + // A Sequence is inherently mutable + template + struct _SequenceConcept + { + typedef typename _Sequence::reference _Reference; + typedef typename _Sequence::const_reference _Const_reference; + + void __constraints() { + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // function_requires< DefaultConstructible >(); + __function_requires< _Mutable_ForwardContainerConcept<_Sequence> >(); + __function_requires< _DefaultConstructibleConcept<_Sequence> >(); + + _Sequence + __c _IsUnused(__n, __t), + __c2 _IsUnused(__first, __last); + + __c.insert(__p, __t); + __c.insert(__p, __n, __t); + __c.insert(__p, __first, __last); + + __c.erase(__p); + __c.erase(__p, __q); + + _Reference __r _IsUnused = __c.front(); + + __const_constraints(__c); + } + void __const_constraints(const _Sequence& __c) { + _Const_reference __r _IsUnused = __c.front(); + } + typename _Sequence::value_type __t; + typename _Sequence::size_type __n; + typename _Sequence::value_type *__first, *__last; + typename _Sequence::iterator __p, __q; + }; + + template + struct _FrontInsertionSequenceConcept + { + void __constraints() { + __function_requires< _SequenceConcept<_FrontInsertionSequence> >(); + + __c.push_front(__t); + __c.pop_front(); + } + _FrontInsertionSequence __c; + typename _FrontInsertionSequence::value_type __t; + }; + + template + struct _BackInsertionSequenceConcept + { + typedef typename _BackInsertionSequence::reference _Reference; + typedef typename _BackInsertionSequence::const_reference _Const_reference; + + void __constraints() { + __function_requires< _SequenceConcept<_BackInsertionSequence> >(); + + __c.push_back(__t); + __c.pop_back(); + _Reference __r _IsUnused = __c.back(); + } + void __const_constraints(const _BackInsertionSequence& __c) { + _Const_reference __r _IsUnused = __c.back(); + }; + _BackInsertionSequence __c; + typename _BackInsertionSequence::value_type __t; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop +#undef _IsUnused + +#endif // _GLIBCXX_BOOST_CONCEPT_CHECK + + diff --git a/template/sysroot/include/bits/c++0x_warning.h b/template/sysroot/include/bits/c++0x_warning.h new file mode 100644 index 0000000..6a4bf6c --- /dev/null +++ b/template/sysroot/include/bits/c++0x_warning.h @@ -0,0 +1,37 @@ +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++0x_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _CXX0X_WARNING_H +#define _CXX0X_WARNING_H 1 + +#if __cplusplus < 201103L +#error This file requires compiler and library support \ +for the ISO C++ 2011 standard. This support must be enabled \ +with the -std=c++11 or -std=gnu++11 compiler options. +#endif + +#endif diff --git a/template/sysroot/include/bits/c++allocator.h b/template/sysroot/include/bits/c++allocator.h new file mode 100644 index 0000000..a2f608f --- /dev/null +++ b/template/sysroot/include/bits/c++allocator.h @@ -0,0 +1,64 @@ +// Base to std::allocator -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_CXX_ALLOCATOR_H +#define _GLIBCXX_CXX_ALLOCATOR_H 1 + +#include + +#if __cplusplus >= 201103L +namespace std +{ + /** + * @brief An alias to the base class for std::allocator. + * + * Used to set the std::allocator base class to std::__new_allocator. + * + * @ingroup allocators + * @tparam _Tp Type of allocated object. + */ + template + using __allocator_base = __new_allocator<_Tp>; +} +#else +// Define __new_allocator as the base class to std::allocator. +# define __allocator_base __new_allocator +#endif + +#ifndef _GLIBCXX_SANITIZE_STD_ALLOCATOR +# if defined(__SANITIZE_ADDRESS__) +# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1 +# elif defined __has_feature +# if __has_feature(address_sanitizer) +# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1 +# endif +# endif +#endif + +#endif diff --git a/template/sysroot/include/bits/c++config.h b/template/sysroot/include/bits/c++config.h new file mode 100644 index 0000000..04f301d --- /dev/null +++ b/template/sysroot/include/bits/c++config.h @@ -0,0 +1,1836 @@ +// Predefined symbols and macros -*- C++ -*- + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++config.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{version} + */ + +#ifndef _GLIBCXX_CXX_CONFIG_H +#define _GLIBCXX_CXX_CONFIG_H 1 + +#pragma GCC system_header + +// The major release number for the GCC release the C++ library belongs to. +#define _GLIBCXX_RELEASE 14 + +// The datestamp of the C++ library in compressed ISO date format. +#define __GLIBCXX__ 20240801 + +// Macros for various attributes. +// _GLIBCXX_PURE +// _GLIBCXX_CONST +// _GLIBCXX_NORETURN +// _GLIBCXX_NOTHROW +// _GLIBCXX_VISIBILITY +#ifndef _GLIBCXX_PURE +# define _GLIBCXX_PURE __attribute__ ((__pure__)) +#endif + +#ifndef _GLIBCXX_CONST +# define _GLIBCXX_CONST __attribute__ ((__const__)) +#endif + +#ifndef _GLIBCXX_NORETURN +# define _GLIBCXX_NORETURN __attribute__ ((__noreturn__)) +#endif + +// See below for C++ +#ifndef _GLIBCXX_NOTHROW +# ifndef __cplusplus +# define _GLIBCXX_NOTHROW __attribute__((__nothrow__)) +# endif +#endif + +// Macros for visibility attributes. +// _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +// _GLIBCXX_VISIBILITY +# define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY 1 + +#if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V))) +#else +// If this is not supplied by the OS-specific or CPU-specific +// headers included below, it will be defined to an empty default. +# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Macros for deprecated attributes. +// _GLIBCXX_USE_DEPRECATED +// _GLIBCXX_DEPRECATED +// _GLIBCXX_DEPRECATED_SUGGEST( string-literal ) +// _GLIBCXX11_DEPRECATED +// _GLIBCXX11_DEPRECATED_SUGGEST( string-literal ) +// _GLIBCXX14_DEPRECATED +// _GLIBCXX14_DEPRECATED_SUGGEST( string-literal ) +// _GLIBCXX17_DEPRECATED +// _GLIBCXX17_DEPRECATED_SUGGEST( string-literal ) +// _GLIBCXX20_DEPRECATED +// _GLIBCXX20_DEPRECATED_SUGGEST( string-literal ) +// _GLIBCXX23_DEPRECATED +// _GLIBCXX23_DEPRECATED_SUGGEST( string-literal ) +#ifndef _GLIBCXX_USE_DEPRECATED +# define _GLIBCXX_USE_DEPRECATED 1 +#endif + +#if defined(__DEPRECATED) +# define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) \ + __attribute__ ((__deprecated__ ("use '" ALT "' instead"))) +#else +# define _GLIBCXX_DEPRECATED +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201103L) +# define _GLIBCXX11_DEPRECATED _GLIBCXX_DEPRECATED +# define _GLIBCXX11_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#else +# define _GLIBCXX11_DEPRECATED +# define _GLIBCXX11_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201402L) +# define _GLIBCXX14_DEPRECATED _GLIBCXX_DEPRECATED +# define _GLIBCXX14_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#else +# define _GLIBCXX14_DEPRECATED +# define _GLIBCXX14_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201703L) +# define _GLIBCXX17_DEPRECATED [[__deprecated__]] +# define _GLIBCXX17_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#else +# define _GLIBCXX17_DEPRECATED +# define _GLIBCXX17_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 202002L) +# define _GLIBCXX20_DEPRECATED [[__deprecated__]] +# define _GLIBCXX20_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#else +# define _GLIBCXX20_DEPRECATED +# define _GLIBCXX20_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 202100L) +# define _GLIBCXX23_DEPRECATED [[__deprecated__]] +# define _GLIBCXX23_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#else +# define _GLIBCXX23_DEPRECATED +# define _GLIBCXX23_DEPRECATED_SUGGEST(ALT) +#endif + +// Macros for ABI tag attributes. +#ifndef _GLIBCXX_ABI_TAG_CXX11 +# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) +#endif + +// Macro to warn about unused results. +#if __cplusplus >= 201703L +# define _GLIBCXX_NODISCARD [[__nodiscard__]] +#else +# define _GLIBCXX_NODISCARD +#endif + + + +#if __cplusplus + +// Macro for constexpr, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_CONSTEXPR +# if __cplusplus >= 201103L +# define _GLIBCXX_CONSTEXPR constexpr +# define _GLIBCXX_USE_CONSTEXPR constexpr +# else +# define _GLIBCXX_CONSTEXPR +# define _GLIBCXX_USE_CONSTEXPR const +# endif +#endif + +#ifndef _GLIBCXX14_CONSTEXPR +# if __cplusplus >= 201402L +# define _GLIBCXX14_CONSTEXPR constexpr +# else +# define _GLIBCXX14_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_CONSTEXPR +# if __cplusplus >= 201703L +# define _GLIBCXX17_CONSTEXPR constexpr +# else +# define _GLIBCXX17_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX20_CONSTEXPR +# if __cplusplus >= 202002L +# define _GLIBCXX20_CONSTEXPR constexpr +# else +# define _GLIBCXX20_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX23_CONSTEXPR +# if __cplusplus >= 202100L +# define _GLIBCXX23_CONSTEXPR constexpr +# else +# define _GLIBCXX23_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_INLINE +# if __cplusplus >= 201703L +# define _GLIBCXX17_INLINE inline +# else +# define _GLIBCXX17_INLINE +# endif +#endif + +// Macro for noexcept, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_NOEXCEPT +# if __cplusplus >= 201103L +# define _GLIBCXX_NOEXCEPT noexcept +# define _GLIBCXX_NOEXCEPT_IF(...) noexcept(__VA_ARGS__) +# define _GLIBCXX_USE_NOEXCEPT noexcept +# define _GLIBCXX_THROW(_EXC) +# else +# define _GLIBCXX_NOEXCEPT +# define _GLIBCXX_NOEXCEPT_IF(...) +# define _GLIBCXX_USE_NOEXCEPT throw() +# define _GLIBCXX_THROW(_EXC) throw(_EXC) +# endif +#endif + +#ifndef _GLIBCXX_NOTHROW +# define _GLIBCXX_NOTHROW _GLIBCXX_USE_NOEXCEPT +#endif + +#ifndef _GLIBCXX_THROW_OR_ABORT +# if __cpp_exceptions +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC)) +# else +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) +# endif +#endif + +#if __cpp_noexcept_function_type +#define _GLIBCXX_NOEXCEPT_PARM , bool _NE +#define _GLIBCXX_NOEXCEPT_QUAL noexcept (_NE) +#else +#define _GLIBCXX_NOEXCEPT_PARM +#define _GLIBCXX_NOEXCEPT_QUAL +#endif + +// Macro for extern template, ie controlling template linkage via use +// of extern keyword on template declaration. As documented in the g++ +// manual, it inhibits all implicit instantiations and is used +// throughout the library to avoid multiple weak definitions for +// required types that are already explicitly instantiated in the +// library binary. This substantially reduces the binary size of +// resulting executables. +// Special case: _GLIBCXX_EXTERN_TEMPLATE == -1 disallows extern +// templates only in basic_string, thus activating its debug-mode +// checks even at -O0. +# define _GLIBCXX_EXTERN_TEMPLATE 1 + +/* + Outline of libstdc++ namespaces. + + namespace std + { + namespace __debug { } + namespace __parallel { } + namespace __cxx1998 { } + + namespace __detail { + namespace __variant { } // C++17 + } + + namespace rel_ops { } + + namespace tr1 + { + namespace placeholders { } + namespace regex_constants { } + namespace __detail { } + } + + namespace tr2 { } + + namespace decimal { } + + namespace chrono { } // C++11 + namespace placeholders { } // C++11 + namespace regex_constants { } // C++11 + namespace this_thread { } // C++11 + inline namespace literals { // C++14 + inline namespace chrono_literals { } // C++14 + inline namespace complex_literals { } // C++14 + inline namespace string_literals { } // C++14 + inline namespace string_view_literals { } // C++17 + } + } + + namespace abi { } + + namespace __gnu_cxx + { + namespace __detail { } + } + + For full details see: + http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/namespaces.html +*/ +namespace std +{ + typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; + +#if __cplusplus >= 201103L + typedef decltype(nullptr) nullptr_t; +#endif + +#pragma GCC visibility push(default) + // This allows the library to terminate without including all of + // and without making the declaration of std::terminate visible to users. + extern "C++" __attribute__ ((__noreturn__, __always_inline__)) + inline void __terminate() _GLIBCXX_USE_NOEXCEPT + { + void terminate() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__noreturn__,__cold__)); + terminate(); + } +#pragma GCC visibility pop +} + +# define _GLIBCXX_USE_DUAL_ABI 1 + +#if ! _GLIBCXX_USE_DUAL_ABI +// Ignore any pre-defined value of _GLIBCXX_USE_CXX11_ABI +# undef _GLIBCXX_USE_CXX11_ABI +#endif + +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + +#if _GLIBCXX_USE_CXX11_ABI +namespace std +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +namespace __gnu_cxx +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +# define _GLIBCXX_NAMESPACE_CXX11 __cxx11:: +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 namespace __cxx11 { +# define _GLIBCXX_END_NAMESPACE_CXX11 } +# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11 +#else +# define _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_CXX11 +# define _GLIBCXX_DEFAULT_ABI_TAG +#endif + +// Non-zero if inline namespaces are used for versioning the entire library. +# define _GLIBCXX_INLINE_VERSION 0 + +#if _GLIBCXX_INLINE_VERSION +// Inline namespace for symbol versioning of (nearly) everything in std. +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 { +# define _GLIBCXX_END_NAMESPACE_VERSION } +// Unused when everything in std is versioned anyway. +# define _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(X) +# define _GLIBCXX_END_INLINE_ABI_NAMESPACE(X) + +namespace std +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __cplusplus >= 201402L + inline namespace literals { + inline namespace chrono_literals { } + inline namespace complex_literals { } + inline namespace string_literals { } +#if __cplusplus > 201402L + inline namespace string_view_literals { } +#endif // C++17 + } +#endif // C++14 +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace __gnu_cxx +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_END_NAMESPACE_VERSION +} + +#else +// Unused. +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION +# define _GLIBCXX_END_NAMESPACE_VERSION +// Used to version individual components, e.g. std::_V2::error_category. +# define _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(X) inline namespace X { +# define _GLIBCXX_END_INLINE_ABI_NAMESPACE(X) } // inline namespace X +#endif + +// In the case that we don't have a hosted environment, we can't provide the +// debugging mode. Instead, we do our best and downgrade to assertions. +#if defined(_GLIBCXX_DEBUG) && !__STDC_HOSTED__ +#undef _GLIBCXX_DEBUG +#define _GLIBCXX_ASSERTIONS 1 +#endif + +// Inline namespaces for special modes: debug, parallel. +#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Non-inline namespace for components replaced by alternates in active mode. + namespace __cxx1998 + { +# if _GLIBCXX_USE_CXX11_ABI + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +# endif + } + +_GLIBCXX_END_NAMESPACE_VERSION + + // Inline namespace for debug mode. +# ifdef _GLIBCXX_DEBUG + inline namespace __debug { } +# endif + + // Inline namespaces for parallel mode. +# ifdef _GLIBCXX_PARALLEL + inline namespace __parallel { } +# endif +} + +// Check for invalid usage and unsupported mixed-mode use. +# if defined(_GLIBCXX_DEBUG) && defined(_GLIBCXX_PARALLEL) +# error illegal use of multiple inlined namespaces +# endif + +// Check for invalid use due to lack for weak symbols. +# if __NO_INLINE__ && !__GXX_WEAK__ +# warning currently using inlined namespace mode which may fail \ + without inlining due to lack of weak symbols +# endif +#endif + +// Macros for namespace scope. Either namespace std:: or the name +// of some nested namespace within it corresponding to the active mode. +// _GLIBCXX_STD_A +// _GLIBCXX_STD_C +// +// Macros for opening/closing conditional namespaces. +// _GLIBCXX_BEGIN_NAMESPACE_ALGO +// _GLIBCXX_END_NAMESPACE_ALGO +// _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +// _GLIBCXX_END_NAMESPACE_CONTAINER +#if defined(_GLIBCXX_DEBUG) +# define _GLIBCXX_STD_C __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \ + namespace _GLIBCXX_STD_C { +# define _GLIBCXX_END_NAMESPACE_CONTAINER } +#else +# define _GLIBCXX_STD_C std +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +# define _GLIBCXX_END_NAMESPACE_CONTAINER +#endif + +#ifdef _GLIBCXX_PARALLEL +# define _GLIBCXX_STD_A __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO \ + namespace _GLIBCXX_STD_A { +# define _GLIBCXX_END_NAMESPACE_ALGO } +#else +# define _GLIBCXX_STD_A std +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO +# define _GLIBCXX_END_NAMESPACE_ALGO +#endif + +// GLIBCXX_ABI Deprecated +// Define if compatibility should be provided for -mlong-double-64. +#undef _GLIBCXX_LONG_DOUBLE_COMPAT + +// Define if compatibility should be provided for alternative 128-bit long +// double formats. Not possible for Clang until __ibm128 is supported. +#ifndef __clang__ +#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT +#endif + +// Inline namespaces for long double 128 modes. +#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ + && defined __LONG_DOUBLE_IEEE128__ +namespace std +{ + // Namespaces for 128-bit IEEE long double format on 64-bit POWER LE. + inline namespace __gnu_cxx_ieee128 { } + inline namespace __gnu_cxx11_ieee128 { } +} +# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ieee128:: +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ieee128 { +# define _GLIBCXX_END_NAMESPACE_LDBL } +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 __gnu_cxx11_ieee128:: +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 namespace __gnu_cxx11_ieee128 { +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 } + +#else // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128 + +#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ +namespace std +{ + inline namespace __gnu_cxx_ldbl128 { } +} +# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ldbl128:: +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ldbl128 { +# define _GLIBCXX_END_NAMESPACE_LDBL } +#else +# define _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL +#endif + +#if _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_CXX11 +#else +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL +#endif + +#endif // _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && IEEE128 + +namespace std +{ +#pragma GCC visibility push(default) + // Internal version of std::is_constant_evaluated(). + // This can be used without checking if the compiler supports the feature. + // The macro _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED can be used to check if + // the compiler support is present to make this function work as expected. + __attribute__((__always_inline__)) + _GLIBCXX_CONSTEXPR inline bool + __is_constant_evaluated() _GLIBCXX_NOEXCEPT + { +#if __cpp_if_consteval >= 202106L +# define _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED 1 + if consteval { return true; } else { return false; } +#elif __cplusplus >= 201103L && __has_builtin(__builtin_is_constant_evaluated) +# define _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED 1 + return __builtin_is_constant_evaluated(); +#else + return false; +#endif + } +#pragma GCC visibility pop +} + +// Debug Mode implies checking assertions. +#if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS) +# define _GLIBCXX_ASSERTIONS 1 +#endif + +// Disable std::string explicit instantiation declarations in order to assert. +#ifdef _GLIBCXX_ASSERTIONS +# undef _GLIBCXX_EXTERN_TEMPLATE +# define _GLIBCXX_EXTERN_TEMPLATE -1 +#endif + +#undef _GLIBCXX_VERBOSE_ASSERT + +// Assert. +#ifdef _GLIBCXX_VERBOSE_ASSERT +namespace std +{ +#pragma GCC visibility push(default) + // Don't use because this should be unaffected by NDEBUG. + extern "C++" _GLIBCXX_NORETURN + void + __glibcxx_assert_fail /* Called when a precondition violation is detected. */ + (const char* __file, int __line, const char* __function, + const char* __condition) + _GLIBCXX_NOEXCEPT; +#pragma GCC visibility pop +} +# define _GLIBCXX_ASSERT_FAIL(_Condition) \ + std::__glibcxx_assert_fail(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #_Condition) +#else // ! VERBOSE_ASSERT +# define _GLIBCXX_ASSERT_FAIL(_Condition) __builtin_abort() +#endif + +#if defined(_GLIBCXX_ASSERTIONS) +// Enable runtime assertion checks, and also check in constant expressions. +# define __glibcxx_assert(cond) \ + do { \ + if (__builtin_expect(!bool(cond), false)) \ + _GLIBCXX_ASSERT_FAIL(cond); \ + } while (false) +#elif _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED +// Only check assertions during constant evaluation. +namespace std +{ + __attribute__((__always_inline__,__visibility__("default"))) + inline void + __glibcxx_assert_fail() + { } +} +# define __glibcxx_assert(cond) \ + do { \ + if (std::__is_constant_evaluated()) \ + if (__builtin_expect(!bool(cond), false)) \ + std::__glibcxx_assert_fail(); \ + } while (false) +#else +// Don't check any assertions. +# define __glibcxx_assert(cond) +#endif + +// Macro indicating that TSAN is in use. +#if __SANITIZE_THREAD__ +# define _GLIBCXX_TSAN 1 +#elif defined __has_feature +# if __has_feature(thread_sanitizer) +# define _GLIBCXX_TSAN 1 +# endif +#endif + +// Macros for race detectors. +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain +// atomic (lock-free) synchronization to race detectors: +// the race detector will infer a happens-before arc from the former to the +// latter when they share the same argument pointer. +// +// The most frequent use case for these macros (and the only case in the +// current implementation of the library) is atomic reference counting: +// void _M_remove_reference() +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount); +// if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0) +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount); +// _M_destroy(__a); +// } +// } +// The annotations in this example tell the race detector that all memory +// accesses occurred when the refcount was positive do not race with +// memory accesses which occurred after the refcount became zero. +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) +#endif +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) +#endif + +// Macros for C linkage: define extern "C" linkage only when using C++. +# define _GLIBCXX_BEGIN_EXTERN_C extern "C" { +# define _GLIBCXX_END_EXTERN_C } + +# define _GLIBCXX_USE_ALLOCATOR_NEW 1 + +#ifdef __SIZEOF_INT128__ +#if ! defined __GLIBCXX_TYPE_INT_N_0 && ! defined __STRICT_ANSI__ +// If __int128 is supported, we expect __GLIBCXX_TYPE_INT_N_0 to be defined +// unless the compiler is in strict mode. If it's not defined and the strict +// macro is not defined, something is wrong. +#warning "__STRICT_ANSI__ seems to have been undefined; this is not supported" +#endif +#endif + +#else // !__cplusplus +# define _GLIBCXX_BEGIN_EXTERN_C +# define _GLIBCXX_END_EXTERN_C +#endif + + +// First includes. + +// Pick up any OS-specific definitions. +#include + +// Pick up any CPU-specific definitions. +#include + +// If platform uses neither visibility nor psuedo-visibility, +// specify empty default for namespace annotation macros. +#ifndef _GLIBCXX_PSEUDO_VISIBILITY +# define _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Certain function definitions that are meant to be overridable from +// user code are decorated with this macro. For some targets, this +// macro causes these definitions to be weak. +#ifndef _GLIBCXX_WEAK_DEFINITION +# define _GLIBCXX_WEAK_DEFINITION +#endif + +// By default, we assume that __GXX_WEAK__ also means that there is support +// for declaring functions as weak while not defining such functions. This +// allows for referring to functions provided by other libraries (e.g., +// libitm) without depending on them if the respective features are not used. +#ifndef _GLIBCXX_USE_WEAK_REF +# define _GLIBCXX_USE_WEAK_REF __GXX_WEAK__ +#endif + +// Conditionally enable annotations for the Transactional Memory TS on C++11. +// Most of the following conditions are due to limitations in the current +// implementation. +#if __cplusplus >= 201103L && _GLIBCXX_USE_CXX11_ABI \ + && _GLIBCXX_USE_DUAL_ABI && __cpp_transactional_memory >= 201500L \ + && !_GLIBCXX_FULLY_DYNAMIC_STRING && _GLIBCXX_USE_WEAK_REF \ + && _GLIBCXX_USE_ALLOCATOR_NEW +#define _GLIBCXX_TXN_SAFE transaction_safe +#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic +#else +#define _GLIBCXX_TXN_SAFE +#define _GLIBCXX_TXN_SAFE_DYN +#endif + +#if __cplusplus > 201402L +// In C++17 mathematical special functions are in namespace std. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#elif __cplusplus >= 201103L && __STDCPP_WANT_MATH_SPEC_FUNCS__ != 0 +// For C++11 and C++14 they are in namespace std when requested. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#endif + +// The remainder of the prewritten config is automatic; all the +// user hooks are listed above. + +// Create a boolean flag to be used to determine if --fast-math is set. +#ifdef __FAST_MATH__ +# define _GLIBCXX_FAST_MATH 1 +#else +# define _GLIBCXX_FAST_MATH 0 +#endif + +// This marks string literals in header files to be extracted for eventual +// translation. It is primarily used for messages in thrown exceptions; see +// src/functexcept.cc. We use __N because the more traditional _N is used +// for something else under certain OSes (see BADNAMES). +#define __N(msgid) (msgid) + +// For example, is known to #define min and max as macros... +#undef min +#undef max + +// N.B. these _GLIBCXX_USE_C99_XXX macros are defined unconditionally +// so they should be tested with #if not with #ifdef. +#if __cplusplus >= 201103L +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX11_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX11_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX11_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX11_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX11_USE_C99_WCHAR +# endif +#else +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX98_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX98_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX98_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX98_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX98_USE_C99_WCHAR +# endif +#endif + +// Unless explicitly specified, enable char8_t extensions only if the core +// language char8_t feature macro is defined. +#ifndef _GLIBCXX_USE_CHAR8_T +# ifdef __cpp_char8_t +# define _GLIBCXX_USE_CHAR8_T 1 +# endif +#endif +#ifdef _GLIBCXX_USE_CHAR8_T +# define __cpp_lib_char8_t 201907L +#endif + +/* Define if __float128 is supported on this host. */ +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +/* For powerpc64 don't use __float128 when it's the same type as long double. */ +# if !(defined(_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT) && defined(__LONG_DOUBLE_IEEE128__)) +# define _GLIBCXX_USE_FLOAT128 1 +# endif +#endif + +// Define if float has the IEEE binary32 format. +#if __FLT_MANT_DIG__ == 24 \ + && __FLT_MIN_EXP__ == -125 \ + && __FLT_MAX_EXP__ == 128 +# define _GLIBCXX_FLOAT_IS_IEEE_BINARY32 1 +#endif + +// Define if double has the IEEE binary64 format. +#if __DBL_MANT_DIG__ == 53 \ + && __DBL_MIN_EXP__ == -1021 \ + && __DBL_MAX_EXP__ == 1024 +# define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1 +#endif + +// Define if long double has the IEEE binary128 format. +#if __LDBL_MANT_DIG__ == 113 \ + && __LDBL_MIN_EXP__ == -16381 \ + && __LDBL_MAX_EXP__ == 16384 +# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 1 +#endif + +#if defined __cplusplus && defined __BFLT16_DIG__ +namespace __gnu_cxx +{ + typedef __decltype(0.0bf16) __bfloat16_t; +} +#endif + +#ifdef __has_builtin +# ifdef __is_identifier +// Intel and older Clang require !__is_identifier for some built-ins: +# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) || ! __is_identifier(B) +# else +# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) +# endif +#endif + +#if _GLIBCXX_HAS_BUILTIN(__has_unique_object_representations) +# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 +#endif + +#if _GLIBCXX_HAS_BUILTIN(__is_aggregate) +# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 +#endif + +#if _GLIBCXX_HAS_BUILTIN(__builtin_launder) +# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 +#endif + +// Returns 1 if _GLIBCXX_DO_NOT_USE_BUILTIN_TRAITS is not defined and the +// compiler has a corresponding built-in type trait, 0 otherwise. +// _GLIBCXX_DO_NOT_USE_BUILTIN_TRAITS can be defined to disable the use of +// built-in traits. +#ifndef _GLIBCXX_DO_NOT_USE_BUILTIN_TRAITS +# define _GLIBCXX_USE_BUILTIN_TRAIT(BT) _GLIBCXX_HAS_BUILTIN(BT) +#else +# define _GLIBCXX_USE_BUILTIN_TRAIT(BT) 0 +#endif + +// Mark code that should be ignored by the compiler, but seen by Doxygen. +#define _GLIBCXX_DOXYGEN_ONLY(X) + +// PSTL configuration + +#if __cplusplus >= 201703L +// This header is not installed for freestanding: +#if __has_include() +// Preserved here so we have some idea which version of upstream we've pulled in +// #define PSTL_VERSION 9000 + +// For now this defaults to being based on the presence of Thread Building Blocks +# ifndef _GLIBCXX_USE_TBB_PAR_BACKEND +# define _GLIBCXX_USE_TBB_PAR_BACKEND __has_include() +# endif +// This section will need some rework when a new (default) backend type is added +# if _GLIBCXX_USE_TBB_PAR_BACKEND +# define _PSTL_PAR_BACKEND_TBB +# else +# define _PSTL_PAR_BACKEND_SERIAL +# endif + +# define _PSTL_ASSERT(_Condition) __glibcxx_assert(_Condition) +# define _PSTL_ASSERT_MSG(_Condition, _Message) __glibcxx_assert(_Condition) + +#include +#endif // __has_include +#endif // C++17 + +// End of prewritten config; the settings discovered at configure time follow. +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `acosf' function. */ +/* #undef _GLIBCXX_HAVE_ACOSF */ + +/* Define to 1 if you have the `acosl' function. */ +/* #undef _GLIBCXX_HAVE_ACOSL */ + +/* Define to 1 if you have the `aligned_alloc' function. */ +/* #undef _GLIBCXX_HAVE_ALIGNED_ALLOC */ + +/* Define if arc4random is available in . */ +/* #undef _GLIBCXX_HAVE_ARC4RANDOM */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the `asinf' function. */ +/* #undef _GLIBCXX_HAVE_ASINF */ + +/* Define to 1 if you have the `asinl' function. */ +/* #undef _GLIBCXX_HAVE_ASINL */ + +/* Define to 1 if the target assembler supports .symver directive. */ +#define _GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE 1 + +/* Define to 1 if you have the `atan2f' function. */ +/* #undef _GLIBCXX_HAVE_ATAN2F */ + +/* Define to 1 if you have the `atan2l' function. */ +/* #undef _GLIBCXX_HAVE_ATAN2L */ + +/* Define to 1 if you have the `atanf' function. */ +/* #undef _GLIBCXX_HAVE_ATANF */ + +/* Define to 1 if you have the `atanl' function. */ +/* #undef _GLIBCXX_HAVE_ATANL */ + +/* Defined if shared_ptr reference counting should use atomic operations. */ +#define _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY 1 + +/* Define to 1 if you have the `at_quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_AT_QUICK_EXIT */ + +/* Define if C99 float_t and double_t in should be imported in + in namespace std for C++11. */ +/* #undef _GLIBCXX_HAVE_C99_FLT_EVAL_TYPES */ + +/* Define to 1 if the target assembler supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_CC_TLS */ + +/* Define to 1 if you have the `ceilf' function. */ +/* #undef _GLIBCXX_HAVE_CEILF */ + +/* Define to 1 if you have the `ceill' function. */ +/* #undef _GLIBCXX_HAVE_CEILL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_COMPLEX_H */ + +/* Define to 1 if you have the `cosf' function. */ +/* #undef _GLIBCXX_HAVE_COSF */ + +/* Define to 1 if you have the `coshf' function. */ +/* #undef _GLIBCXX_HAVE_COSHF */ + +/* Define to 1 if you have the `coshl' function. */ +/* #undef _GLIBCXX_HAVE_COSHL */ + +/* Define to 1 if you have the `cosl' function. */ +/* #undef _GLIBCXX_HAVE_COSL */ + +/* Define to 1 if you have the declaration of `strnlen', and to 0 if you + don't. */ +#define _GLIBCXX_HAVE_DECL_STRNLEN 0 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DIRENT_H */ + +/* Define if dirfd is available in . */ +/* #undef _GLIBCXX_HAVE_DIRFD */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DLFCN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ENDIAN_H */ + +/* Define to 1 if GCC 4.6 supported std::exception_ptr for the target */ +/* #undef _GLIBCXX_HAVE_EXCEPTION_PTR_SINCE_GCC46 */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_EXECINFO_H */ + +/* Define to 1 if you have the `expf' function. */ +/* #undef _GLIBCXX_HAVE_EXPF */ + +/* Define to 1 if you have the `expl' function. */ +/* #undef _GLIBCXX_HAVE_EXPL */ + +/* Define to 1 if you have the `fabsf' function. */ +/* #undef _GLIBCXX_HAVE_FABSF */ + +/* Define to 1 if you have the `fabsl' function. */ +/* #undef _GLIBCXX_HAVE_FABSL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FCNTL_H */ + +/* Define if fdopendir is available in . */ +/* #undef _GLIBCXX_HAVE_FDOPENDIR */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FENV_H */ + +/* Define to 1 if you have the `finite' function. */ +/* #undef _GLIBCXX_HAVE_FINITE */ + +/* Define to 1 if you have the `finitef' function. */ +/* #undef _GLIBCXX_HAVE_FINITEF */ + +/* Define to 1 if you have the `finitel' function. */ +/* #undef _GLIBCXX_HAVE_FINITEL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `floorf' function. */ +/* #undef _GLIBCXX_HAVE_FLOORF */ + +/* Define to 1 if you have the `floorl' function. */ +/* #undef _GLIBCXX_HAVE_FLOORL */ + +/* Define to 1 if you have the `fmodf' function. */ +/* #undef _GLIBCXX_HAVE_FMODF */ + +/* Define to 1 if you have the `fmodl' function. */ +/* #undef _GLIBCXX_HAVE_FMODL */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef _GLIBCXX_HAVE_FPCLASS */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FP_H */ + +/* Define to 1 if you have the `frexpf' function. */ +/* #undef _GLIBCXX_HAVE_FREXPF */ + +/* Define to 1 if you have the `frexpl' function. */ +/* #undef _GLIBCXX_HAVE_FREXPL */ + +/* Define if getentropy is available in . */ +/* #undef _GLIBCXX_HAVE_GETENTROPY */ + +/* Define if _Unwind_GetIPInfo is available. */ +#define _GLIBCXX_HAVE_GETIPINFO 1 + +/* Define if gets is available in before C++14. */ +/* #undef _GLIBCXX_HAVE_GETS */ + +/* Define to 1 if you have the `hypot' function. */ +/* #undef _GLIBCXX_HAVE_HYPOT */ + +/* Define to 1 if you have the `hypotf' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTF */ + +/* Define to 1 if you have the `hypotl' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTL */ + +/* Define if you have the iconv() function and it works. */ +/* #undef _GLIBCXX_HAVE_ICONV */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_IEEEFP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_INTTYPES_H */ + +/* Define to 1 if you have the `isinf' function. */ +/* #undef _GLIBCXX_HAVE_ISINF */ + +/* Define to 1 if you have the `isinff' function. */ +/* #undef _GLIBCXX_HAVE_ISINFF */ + +/* Define to 1 if you have the `isinfl' function. */ +/* #undef _GLIBCXX_HAVE_ISINFL */ + +/* Define to 1 if you have the `isnan' function. */ +/* #undef _GLIBCXX_HAVE_ISNAN */ + +/* Define to 1 if you have the `isnanf' function. */ +/* #undef _GLIBCXX_HAVE_ISNANF */ + +/* Define to 1 if you have the `isnanl' function. */ +/* #undef _GLIBCXX_HAVE_ISNANL */ + +/* Defined if iswblank exists. */ +/* #undef _GLIBCXX_HAVE_ISWBLANK */ + +/* Define if LC_MESSAGES is available in . */ +/* #undef _GLIBCXX_HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the `ldexpf' function. */ +/* #undef _GLIBCXX_HAVE_LDEXPF */ + +/* Define to 1 if you have the `ldexpl' function. */ +/* #undef _GLIBCXX_HAVE_LDEXPL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LIBINTL_H */ + +/* Only used in build directory testsuite_hooks.h. */ +/* #undef _GLIBCXX_HAVE_LIMIT_AS */ + +/* Only used in build directory testsuite_hooks.h. */ +/* #undef _GLIBCXX_HAVE_LIMIT_DATA */ + +/* Only used in build directory testsuite_hooks.h. */ +/* #undef _GLIBCXX_HAVE_LIMIT_FSIZE */ + +/* Only used in build directory testsuite_hooks.h. */ +/* #undef _GLIBCXX_HAVE_LIMIT_RSS */ + +/* Only used in build directory testsuite_hooks.h. */ +/* #undef _GLIBCXX_HAVE_LIMIT_VMEM */ + +/* Define if link is available in . */ +/* #undef _GLIBCXX_HAVE_LINK */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINK_H */ + +/* Define if futex syscall is available. */ +/* #undef _GLIBCXX_HAVE_LINUX_FUTEX */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_RANDOM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_TYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LOCALE_H */ + +/* Define to 1 if you have the `log10f' function. */ +/* #undef _GLIBCXX_HAVE_LOG10F */ + +/* Define to 1 if you have the `log10l' function. */ +/* #undef _GLIBCXX_HAVE_LOG10L */ + +/* Define to 1 if you have the `logf' function. */ +/* #undef _GLIBCXX_HAVE_LOGF */ + +/* Define to 1 if you have the `logl' function. */ +/* #undef _GLIBCXX_HAVE_LOGL */ + +/* Define if lseek is available in . */ +/* #undef _GLIBCXX_HAVE_LSEEK */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_MACHINE_ENDIAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_MACHINE_PARAM_H */ + +/* Define if mbstate_t exists in wchar.h. */ +/* #undef _GLIBCXX_HAVE_MBSTATE_T */ + +/* Define to 1 if you have the `memalign' function. */ +/* #undef _GLIBCXX_HAVE_MEMALIGN */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_MEMORY_H */ + +/* Define to 1 if you have the `modf' function. */ +/* #undef _GLIBCXX_HAVE_MODF */ + +/* Define to 1 if you have the `modff' function. */ +/* #undef _GLIBCXX_HAVE_MODFF */ + +/* Define to 1 if you have the `modfl' function. */ +/* #undef _GLIBCXX_HAVE_MODFL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_TCP_H */ + +/* Define if defines obsolete isinf function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISINF */ + +/* Define if defines obsolete isnan function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISNAN */ + +/* Define if openat is available in . */ +/* #undef _GLIBCXX_HAVE_OPENAT */ + +/* Define if poll is available in . */ +/* #undef _GLIBCXX_HAVE_POLL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_memalign' function. */ +/* #undef _GLIBCXX_HAVE_POSIX_MEMALIGN */ + +/* Define to 1 if POSIX Semaphores with sem_timedwait are available in + . */ +/* #undef _GLIBCXX_HAVE_POSIX_SEMAPHORE */ + +/* Define to 1 if you have the `powf' function. */ +/* #undef _GLIBCXX_HAVE_POWF */ + +/* Define to 1 if you have the `powl' function. */ +/* #undef _GLIBCXX_HAVE_POWL */ + +/* Define to 1 if you have the `qfpclass' function. */ +/* #undef _GLIBCXX_HAVE_QFPCLASS */ + +/* Define to 1 if you have the `quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_QUICK_EXIT */ + +/* Define if readlink is available in . */ +/* #undef _GLIBCXX_HAVE_READLINK */ + +/* Define to 1 if you have the `secure_getenv' function. */ +/* #undef _GLIBCXX_HAVE_SECURE_GETENV */ + +/* Define to 1 if you have the `setenv' function. */ +/* #undef _GLIBCXX_HAVE_SETENV */ + +/* Define to 1 if you have the `sincos' function. */ +/* #undef _GLIBCXX_HAVE_SINCOS */ + +/* Define to 1 if you have the `sincosf' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSF */ + +/* Define to 1 if you have the `sincosl' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSL */ + +/* Define to 1 if you have the `sinf' function. */ +/* #undef _GLIBCXX_HAVE_SINF */ + +/* Define to 1 if you have the `sinhf' function. */ +/* #undef _GLIBCXX_HAVE_SINHF */ + +/* Define to 1 if you have the `sinhl' function. */ +/* #undef _GLIBCXX_HAVE_SINHL */ + +/* Define to 1 if you have the `sinl' function. */ +/* #undef _GLIBCXX_HAVE_SINL */ + +/* Defined if sleep exists. */ +/* #undef _GLIBCXX_HAVE_SLEEP */ + +/* Define to 1 if you have the `sockatmark' function. */ +/* #undef _GLIBCXX_HAVE_SOCKATMARK */ + +/* Define to 1 if you have the `sqrtf' function. */ +/* #undef _GLIBCXX_HAVE_SQRTF */ + +/* Define to 1 if you have the `sqrtl' function. */ +/* #undef _GLIBCXX_HAVE_SQRTL */ + +/* Define if the header is supported. */ +/* #undef _GLIBCXX_HAVE_STACKTRACE */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDALIGN_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_STDLIB_H */ + +/* Define if strerror_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRERROR_L */ + +/* Define if strerror_r is available in . */ +/* #undef _GLIBCXX_HAVE_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_STRINGS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_STRING_H */ + +/* Define to 1 if you have the `strtof' function. */ +/* #undef _GLIBCXX_HAVE_STRTOF */ + +/* Define to 1 if you have the `strtold' function. */ +/* #undef _GLIBCXX_HAVE_STRTOLD */ + +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +/* #undef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE */ + +/* Define if strxfrm_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRXFRM_L */ + +/* Define if symlink is available in . */ +/* #undef _GLIBCXX_HAVE_SYMLINK */ + +/* Define to 1 if the target runtime linker supports binding the same symbol + to different versions. */ +/* #undef _GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_ISA_DEFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_MACHINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have a suitable header file */ +/* #undef _GLIBCXX_HAVE_SYS_SDT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_STATVFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_STAT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SYSINFO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_TYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_UIO_H */ + +/* Define if S_IFREG is available in . */ +/* #undef _GLIBCXX_HAVE_S_IFREG */ + +/* Define if S_ISREG is available in . */ +/* #undef _GLIBCXX_HAVE_S_ISREG */ + +/* Define to 1 if you have the `tanf' function. */ +/* #undef _GLIBCXX_HAVE_TANF */ + +/* Define to 1 if you have the `tanhf' function. */ +/* #undef _GLIBCXX_HAVE_TANHF */ + +/* Define to 1 if you have the `tanhl' function. */ +/* #undef _GLIBCXX_HAVE_TANHL */ + +/* Define to 1 if you have the `tanl' function. */ +/* #undef _GLIBCXX_HAVE_TANL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_TGMATH_H */ + +/* Define to 1 if you have the `timespec_get' function. */ +/* #undef _GLIBCXX_HAVE_TIMESPEC_GET */ + +/* Define to 1 if the target supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_TLS */ + +/* Define if truncate is available in . */ +/* #undef _GLIBCXX_HAVE_TRUNCATE */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_UCHAR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_UNISTD_H */ + +/* Define if unlinkat is available in . */ +/* #undef _GLIBCXX_HAVE_UNLINKAT */ + +/* Define to 1 if you have the `uselocale' function. */ +/* #undef _GLIBCXX_HAVE_USELOCALE */ + +/* Defined if usleep exists. */ +/* #undef _GLIBCXX_HAVE_USLEEP */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_UTIME_H */ + +/* Defined if vfwscanf exists. */ +/* #undef _GLIBCXX_HAVE_VFWSCANF */ + +/* Defined if vswscanf exists. */ +/* #undef _GLIBCXX_HAVE_VSWSCANF */ + +/* Defined if vwscanf exists. */ +/* #undef _GLIBCXX_HAVE_VWSCANF */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_WCHAR_H */ + +/* Defined if wcstof exists. */ +/* #undef _GLIBCXX_HAVE_WCSTOF */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_WCTYPE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_WINDOWS_H */ + +/* Define if writev is available in . */ +/* #undef _GLIBCXX_HAVE_WRITEV */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_XLOCALE_H */ + +/* Define to 1 if you have the `_aligned_malloc' function. */ +/* #undef _GLIBCXX_HAVE__ALIGNED_MALLOC */ + +/* Define to 1 if you have the `_wfopen' function. */ +/* #undef _GLIBCXX_HAVE__WFOPEN */ + +/* Define to 1 if you have the `__cxa_thread_atexit' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT */ + +/* Define to 1 if you have the `__cxa_thread_atexit_impl' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef _GLIBCXX_ICONV_CONST */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define _GLIBCXX_LT_OBJDIR ".libs/" + +/* Name of package */ +/* #undef _GLIBCXX_PACKAGE */ + +/* Define to the address where bug reports for this package should be sent. */ +#define _GLIBCXX_PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define _GLIBCXX_PACKAGE_NAME "package-unused" + +/* Define to the full name and version of this package. */ +#define _GLIBCXX_PACKAGE_STRING "package-unused version-unused" + +/* Define to the one symbol short name of this package. */ +#define _GLIBCXX_PACKAGE_TARNAME "libstdc++" + +/* Define to the home page for this package. */ +#define _GLIBCXX_PACKAGE_URL "" + +/* Define to the version of this package. */ +#define _GLIBCXX_PACKAGE__GLIBCXX_VERSION "version-unused" + +/* Define to 1 if you have the ANSI C header files. */ +/* #undef _GLIBCXX_STDC_HEADERS */ + +/* Version number of package */ +/* #undef _GLIBCXX_VERSION */ + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _GLIBCXX_DARWIN_USE_64_BIT_INODE +# define _GLIBCXX_DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _GLIBCXX_FILE_OFFSET_BITS */ + +/* Define if C99 functions in should be used in for + C++11. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX11_USE_C99_COMPLEX */ + +/* Define if C99 generic macros in should be imported in in + namespace std for C++11. */ +/* #undef _GLIBCXX11_USE_C99_MATH */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +/* #undef _GLIBCXX11_USE_C99_STDIO */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +/* #undef _GLIBCXX11_USE_C99_STDLIB */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +/* #undef _GLIBCXX11_USE_C99_WCHAR */ + +/* Define if C99 functions in should be used in for + C++98. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX98_USE_C99_COMPLEX */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +/* #undef _GLIBCXX98_USE_C99_MATH */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +/* #undef _GLIBCXX98_USE_C99_STDIO */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +/* #undef _GLIBCXX98_USE_C99_STDLIB */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +/* #undef _GLIBCXX98_USE_C99_WCHAR */ + +/* Define if the compiler supports C++11 atomics. */ +#define _GLIBCXX_ATOMIC_BUILTINS 1 + +/* Define if global objects can be aligned to + std::hardware_destructive_interference_size. */ +#define _GLIBCXX_CAN_ALIGNAS_DESTRUCTIVE_SIZE 1 + +/* Define to use concept checking code from the boost libraries. */ +/* #undef _GLIBCXX_CONCEPT_CHECKS */ + +/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, + undefined for platform defaults */ +#define _GLIBCXX_FULLY_DYNAMIC_STRING 0 + +/* Define if gthreads library is available. */ +/* #undef _GLIBCXX_HAS_GTHREADS */ + +/* Define to 1 if a full hosted library is built, or 0 if freestanding. */ +#define _GLIBCXX_HOSTED 0 + +/* Define if compatibility should be provided for alternative 128-bit long + double formats. */ + +/* Define if compatibility should be provided for -mlong-double-64. */ + +/* Define to the letter to which size_t is mangled. */ +#define _GLIBCXX_MANGLE_SIZE_T m + +/* Define if C99 llrint and llround functions are missing from . */ +/* #undef _GLIBCXX_NO_C99_ROUNDING_FUNCS */ + +/* Defined if no way to sleep is available. */ +/* #undef _GLIBCXX_NO_SLEEP */ + +/* Define if ptrdiff_t is int. */ +/* #undef _GLIBCXX_PTRDIFF_T_IS_INT */ + +/* Define if using setrlimit to set resource limits during "make check" */ +/* #undef _GLIBCXX_RES_LIMITS */ + +/* Define if size_t is unsigned int. */ +/* #undef _GLIBCXX_SIZE_T_IS_UINT */ + +/* Define if static tzdata should be compiled into the library. */ +#define _GLIBCXX_STATIC_TZDATA 1 + +/* Define to the value of the EOF integer constant. */ +/* #undef _GLIBCXX_STDIO_EOF */ + +/* Define to the value of the SEEK_CUR integer constant. */ +/* #undef _GLIBCXX_STDIO_SEEK_CUR */ + +/* Define to the value of the SEEK_END integer constant. */ +/* #undef _GLIBCXX_STDIO_SEEK_END */ + +/* Define to use symbol versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER */ + +/* Define to use darwin versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_DARWIN */ + +/* Define to use GNU versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU */ + +/* Define to use GNU namespace versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU_NAMESPACE */ + +/* Define to use Sun versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_SUN */ + +/* Define if C11 functions in should be imported into namespace std + in . */ +/* #undef _GLIBCXX_USE_C11_UCHAR_CXX11 */ + +/* Define if C99 functions or macros from , , , + , and can be used or exposed. */ +/* #undef _GLIBCXX_USE_C99 */ + +/* Define if C99 inverse trig functions in should be used in + . Using compiler builtins for these functions requires + corresponding C99 library functions to be present. */ +/* #undef _GLIBCXX_USE_C99_COMPLEX_ARC */ + +/* Define if C99 functions in should be used in . + Using compiler builtins for these functions requires corresponding C99 + library functions to be present. */ +/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ + +/* Define if C99 functions in should be imported in in + namespace std for C++11. */ +/* #undef _GLIBCXX_USE_C99_CTYPE */ + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_CTYPE_TR1 */ + +/* Define if C99 functions in should be imported in in + namespace std for C++11. */ +/* #undef _GLIBCXX_USE_C99_FENV */ + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_FENV_TR1 */ + +/* Define if C99 functions in should be imported in + in namespace std in C++11. */ +/* #undef _GLIBCXX_USE_C99_INTTYPES */ + +/* Define if C99 functions in should be imported in + in namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_INTTYPES_TR1 */ + +/* Define if wchar_t C99 functions in should be imported in + in namespace std in C++11. */ +/* #undef _GLIBCXX_USE_C99_INTTYPES_WCHAR_T */ + +/* Define if wchar_t C99 functions in should be imported in + in namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 */ + +/* Define if C99 functions in should be imported in in + namespace std for C++11. */ +/* #undef _GLIBCXX_USE_C99_MATH_FUNCS */ + +/* Define if C99 functions or macros in should be imported in + in namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_MATH_TR1 */ + +/* Define if C99 types in should be imported in in + namespace std for C++11. */ +/* #undef _GLIBCXX_USE_C99_STDINT */ + +/* Define if C99 types in should be imported in in + namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_STDINT_TR1 */ + +/* Define if usable chdir is available in . */ +/* #undef _GLIBCXX_USE_CHDIR */ + +/* Define if usable chmod is available in . */ +/* #undef _GLIBCXX_USE_CHMOD */ + +/* Defined if clock_gettime syscall has monotonic and realtime clock support. + */ +/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */ + +/* Defined if clock_gettime has monotonic clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_MONOTONIC */ + +/* Defined if clock_gettime has realtime clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_REALTIME */ + +/* Define if copy_file_range is available in . */ +/* #undef _GLIBCXX_USE_COPY_FILE_RANGE */ + +/* Define if ISO/IEC TR 24733 decimal floating point types are supported on + this host. */ +/* #undef _GLIBCXX_USE_DECIMAL_FLOAT */ + +/* Define if /dev/random and /dev/urandom are available for + std::random_device. */ +/* #undef _GLIBCXX_USE_DEV_RANDOM */ + +/* Define if fchmod is available in . */ +/* #undef _GLIBCXX_USE_FCHMOD */ + +/* Define if fchmodat is available in . */ +/* #undef _GLIBCXX_USE_FCHMODAT */ + +/* Define if fseeko and ftello are available. */ +/* #undef _GLIBCXX_USE_FSEEKO_FTELLO */ + +/* Define if usable getcwd is available in . */ +/* #undef _GLIBCXX_USE_GETCWD */ + +/* Defined if gettimeofday is available. */ +/* #undef _GLIBCXX_USE_GETTIMEOFDAY */ + +/* Define if get_nprocs is available in . */ +/* #undef _GLIBCXX_USE_GET_NPROCS */ + +/* Define if init_priority should be used for iostream initialization. */ +#define _GLIBCXX_USE_INIT_PRIORITY_ATTRIBUTE 1 + +/* Define if LFS support is available. */ +/* #undef _GLIBCXX_USE_LFS */ + +/* Define if code specialized for long long should be used. */ +#define _GLIBCXX_USE_LONG_LONG 1 + +/* Define if lstat is available in . */ +/* #undef _GLIBCXX_USE_LSTAT */ + +/* Define if usable mkdir is available in . */ +/* #undef _GLIBCXX_USE_MKDIR */ + +/* Defined if nanosleep is available. */ +/* #undef _GLIBCXX_USE_NANOSLEEP */ + +/* Define if NLS translations are to be used. */ +/* #undef _GLIBCXX_USE_NLS */ + +/* Define if nl_langinfo_l should be used for std::text_encoding. */ +/* #undef _GLIBCXX_USE_NL_LANGINFO_L */ + +/* Define if pthreads_num_processors_np is available in . */ +/* #undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP */ + +/* Define if pthread_cond_clockwait is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT */ + +/* Define if pthread_mutex_clocklock is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK */ + +/* Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are + available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK */ + +/* Define if POSIX read/write locks are available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_T */ + +/* Define if /dev/random and /dev/urandom are available for the random_device + of TR1 (Chapter 5.1). */ +/* #undef _GLIBCXX_USE_RANDOM_TR1 */ + +/* Define if usable realpath is available in . */ +/* #undef _GLIBCXX_USE_REALPATH */ + +/* Defined if sched_yield is available. */ +/* #undef _GLIBCXX_USE_SCHED_YIELD */ + +/* Define if _SC_NPROCESSORS_ONLN is available in . */ +/* #undef _GLIBCXX_USE_SC_NPROCESSORS_ONLN */ + +/* Define if _SC_NPROC_ONLN is available in . */ +/* #undef _GLIBCXX_USE_SC_NPROC_ONLN */ + +/* Define if sendfile is available in . */ +/* #undef _GLIBCXX_USE_SENDFILE */ + +/* Define to restrict std::__basic_file<> to stdio APIs. */ +/* #undef _GLIBCXX_USE_STDIO_PURE */ + +/* Define if struct stat has timespec members. */ +/* #undef _GLIBCXX_USE_ST_MTIM */ + +/* Define if sysctl(), CTL_HW and HW_NCPU are available in . */ +/* #undef _GLIBCXX_USE_SYSCTL_HW_NCPU */ + +/* Define if obsolescent tmpnam is available in . */ +/* #undef _GLIBCXX_USE_TMPNAM */ + +/* Define if c8rtomb and mbrtoc8 functions in should be imported + into namespace std in for C++20. */ +/* #undef _GLIBCXX_USE_UCHAR_C8RTOMB_MBRTOC8_CXX20 */ + +/* Define if c8rtomb and mbrtoc8 functions in should be imported + into namespace std in for -fchar8_t. */ +/* #undef _GLIBCXX_USE_UCHAR_C8RTOMB_MBRTOC8_FCHAR8_T */ + +/* Define if utime is available in . */ +/* #undef _GLIBCXX_USE_UTIME */ + +/* Define if utimensat and UTIME_OMIT are available in and + AT_FDCWD in . */ +/* #undef _GLIBCXX_USE_UTIMENSAT */ + +/* Define if code specialized for wchar_t should be used. */ +/* #undef _GLIBCXX_USE_WCHAR_T */ + +/* Defined if Sleep exists. */ +/* #undef _GLIBCXX_USE_WIN32_SLEEP */ + +/* Define if _get_osfhandle should be used for filebuf::native_handle(). */ +/* #undef _GLIBCXX_USE__GET_OSFHANDLE */ + +/* Define to 1 if a verbose library is built, or 0 otherwise. */ +#define _GLIBCXX_VERBOSE 0 + +/* Defined if as can handle rdrand. */ +#define _GLIBCXX_X86_RDRAND 1 + +/* Defined if as can handle rdseed. */ +#define _GLIBCXX_X86_RDSEED 1 + +/* Define if a directory should be searched for tzdata files. */ +/* #undef _GLIBCXX_ZONEINFO_DIR */ + +/* Define to 1 if mutex_timedlock is available. */ +/* #undef _GTHREAD_USE_MUTEX_TIMEDLOCK */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _GLIBCXX_LARGE_FILES */ + +/* Define if all C++11 floating point overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP */ +#endif + +/* Define if all C++11 integral type overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT */ +#endif + +#endif // _GLIBCXX_CXX_CONFIG_H diff --git a/template/sysroot/include/bits/c++io.h b/template/sysroot/include/bits/c++io.h new file mode 100644 index 0000000..7b2b4e9 --- /dev/null +++ b/template/sysroot/include/bits/c++io.h @@ -0,0 +1,57 @@ +// Underlying io library details -*- C++ -*- + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++io.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ios} + */ + +// c_io_stdio.h - Defines for using "C" stdio.h + +#ifndef _GLIBCXX_CXX_IO_H +#define _GLIBCXX_CXX_IO_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __GTHREAD_LEGACY_MUTEX_T + // The layout of __gthread_mutex_t changed in GCC 13, but libstdc++ doesn't + // actually use the basic_filebuf::_M_lock member, so define it consistently + // with the old __gthread_mutex_t to avoid an unnecessary layout change: + typedef __GTHREAD_LEGACY_MUTEX_T __c_lock; +#else + typedef __gthread_mutex_t __c_lock; +#endif + + // for basic_file.h + typedef FILE __c_file; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/c++locale.h b/template/sysroot/include/bits/c++locale.h new file mode 100644 index 0000000..ef67a8d --- /dev/null +++ b/template/sysroot/include/bits/c++locale.h @@ -0,0 +1,92 @@ +// Wrapper for underlying C-language localization -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++locale.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.8 Standard locale categories. +// + +// Written by Benjamin Kosnik + +#ifndef _GLIBCXX_CXX_LOCALE_H +#define _GLIBCXX_CXX_LOCALE_H 1 + +#pragma GCC system_header + +#include + +#define _GLIBCXX_NUM_CATEGORIES 0 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + typedef int* __c_locale; + + // Convert numeric value of type double and long double to string and + // return length of string. If vsnprintf is available use it, otherwise + // fall back to the unsafe vsprintf which, in general, can be dangerous + // and should be avoided. + inline int + __convert_from_v(const __c_locale&, char* __out, + const int __size __attribute__((__unused__)), + const char* __fmt, ...) + { + char* __old = std::setlocale(LC_NUMERIC, 0); + char* __sav = 0; + if (__builtin_strcmp(__old, "C")) + { + const size_t __len = __builtin_strlen(__old) + 1; + __sav = new char[__len]; + __builtin_memcpy(__sav, __old, __len); + std::setlocale(LC_NUMERIC, "C"); + } + + __builtin_va_list __args; + __builtin_va_start(__args, __fmt); + +#if _GLIBCXX_USE_C99_STDIO && !_GLIBCXX_HAVE_BROKEN_VSNPRINTF + const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args); +#else + const int __ret = __builtin_vsprintf(__out, __fmt, __args); +#endif + + __builtin_va_end(__args); + + if (__sav) + { + std::setlocale(LC_NUMERIC, __sav); + delete [] __sav; + } + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/char_traits.h b/template/sysroot/include/bits/char_traits.h new file mode 100644 index 0000000..3074e9b --- /dev/null +++ b/template/sysroot/include/bits/char_traits.h @@ -0,0 +1,1017 @@ +// Character Traits for use by standard string and iostream -*- C++ -*- + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/char_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string} + */ + +// +// ISO C++ 14882: 21 Strings library +// + +#ifndef _CHAR_TRAITS_H +#define _CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include + +#if _GLIBCXX_HOSTED +# include // For streampos +#endif // HOSTED + +#ifdef _GLIBCXX_USE_WCHAR_T +# include // For WEOF, wmemmove, wmemset, etc. +#endif // USE_WCHAR_T + +#if __cplusplus >= 201103L +# include +#if !defined __UINT_LEAST16_TYPE__ || !defined __UINT_LEAST32_TYPE__ +# include +#endif +#endif +#if __cplusplus >= 202002L +# include +# include +#endif + +#ifndef _GLIBCXX_ALWAYS_INLINE +# define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#pragma GCC diagnostic ignored "-Wstringop-overread" +#pragma GCC diagnostic ignored "-Warray-bounds" + + /** + * @brief Mapping from character type to associated types. + * + * @note This is an implementation class for the generic version + * of char_traits. It defines int_type, off_type, pos_type, and + * state_type. By default these are unsigned long, streamoff, + * streampos, and mbstate_t. Users who need a different set of + * types, but who don't need to change the definitions of any function + * defined in char_traits, can specialize __gnu_cxx::_Char_types + * while leaving __gnu_cxx::char_traits alone. */ + template + struct _Char_types + { + typedef unsigned long int_type; +#if _GLIBCXX_HOSTED + typedef std::streampos pos_type; + typedef std::streamoff off_type; + typedef std::mbstate_t state_type; +#endif // HOSTED + }; + + + /** + * @brief Base class used to implement std::char_traits. + * + * @note For any given actual character type, this definition is + * probably wrong. (Most of the member functions are likely to be + * right, but the int_type and state_type typedefs, and the eof() + * member function, are likely to be wrong.) The reason this class + * exists is so users can specialize it. Classes in namespace std + * may not be specialized for fundamental types, but classes in + * namespace __gnu_cxx may be. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits + { + typedef _CharT char_type; + typedef typename _Char_types<_CharT>::int_type int_type; +#if _GLIBCXX_HOSTED + typedef typename _Char_types<_CharT>::pos_type pos_type; + typedef typename _Char_types<_CharT>::off_type off_type; + typedef typename _Char_types<_CharT>::state_type state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = std::strong_ordering; +#endif + + static _GLIBCXX14_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static _GLIBCXX14_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX14_CONSTEXPR std::size_t + length(const char_type* __s); + + static _GLIBCXX14_CONSTEXPR const char_type* + find(const char_type* __s, std::size_t __n, const char_type& __a); + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, std::size_t __n, char_type __a); + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + +#ifdef _GLIBCXX_STDIO_EOF + static _GLIBCXX_CONSTEXPR int_type + eof() + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) + { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } +#endif // defined(_GLIBCXX_STDIO_EOF) + }; + + template + _GLIBCXX14_CONSTEXPR int + char_traits<_CharT>:: + compare(const char_type* __s1, const char_type* __s2, std::size_t __n) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + template + _GLIBCXX14_CONSTEXPR std::size_t + char_traits<_CharT>:: + length(const char_type* __p) + { + std::size_t __i = 0; + while (!eq(__p[__i], char_type())) + ++__i; + return __i; + } + + template + _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + find(const char_type* __s, std::size_t __n, const char_type& __a) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + move(char_type* __s1, const char_type* __s2, std::size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + { + // Use __builtin_constant_p to avoid comparing unrelated pointers. + if (__builtin_constant_p(__s2 < __s1) + && __s1 > __s2 && __s1 < (__s2 + __n)) + { + do + { + --__n; + assign(__s1[__n], __s2[__n]); + } + while (__n > 0); + } + else + copy(__s1, __s2, __n); + return __s1; + } +#endif + __builtin_memmove(__s1, __s2, __n * sizeof(char_type)); + return __s1; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + copy(char_type* __s1, const char_type* __s2, std::size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + { + for (std::size_t __i = 0; __i < __n; ++__i) + std::construct_at(__s1 + __i, __s2[__i]); + return __s1; + } +#endif + __builtin_memcpy(__s1, __s2, __n * sizeof(char_type)); + return __s1; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + assign(char_type* __s, std::size_t __n, char_type __a) + { +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + { + for (std::size_t __i = 0; __i < __n; ++__i) + std::construct_at(__s + __i, __a); + return __s; + } +#endif + + if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT)) + { + if (__n) + { + unsigned char __c; + __builtin_memcpy(&__c, __builtin_addressof(__a), 1); + __builtin_memset(__s, __c, __n); + } + } + else + { + for (std::size_t __i = 0; __i < __n; ++__i) + __s[__i] = __a; + } + return __s; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 21.1 + /** + * @brief Basis for explicit traits specializations. + * + * @note For any given actual character type, this definition is + * probably wrong. Since this is just a thin wrapper around + * __gnu_cxx::char_traits, it is possible to achieve a more + * appropriate definition by specializing __gnu_cxx::char_traits. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits : public __gnu_cxx::char_traits<_CharT> + { }; + + + /// 21.1.3.1 char_traits specializations + template<> + struct char_traits + { + typedef char char_type; + typedef int int_type; +#if _GLIBCXX_HOSTED + typedef streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { + // LWG 467. + return (static_cast(__c1) + < static_cast(__c2)); + } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::length(__s); +#endif + return __builtin_strlen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(__c); } + + // To keep both the byte 0xff and the eof symbol 0xffffffff + // from ending up as 0xffffffff. + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(static_cast(__c)); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + +#ifdef _GLIBCXX_STDIO_EOF + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return (__c == eof()) ? 0 : __c; } +#endif // defined(_GLIBCXX_STDIO_EOF) + }; + + +#ifdef _GLIBCXX_USE_WCHAR_T + /// 21.1.3.2 char_traits specializations + template<> + struct char_traits + { + typedef wchar_t char_type; + typedef wint_t int_type; +#if _GLIBCXX_HOSTED + typedef streamoff off_type; + typedef wstreampos pos_type; + typedef mbstate_t state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return wmemcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::length(__s); +#endif + return wcslen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return wmemchr(__s, __a, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return wmemmove(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return wmemcpy(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return wmemset(__s, __a, __n); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + +#if _GLIBCXX_HOSTED + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(WEOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } +#endif // HOSTED + }; +#else // _GLIBCXX_USE_WCHAR_T + template<> + struct char_traits : public __gnu_cxx::char_traits + { }; +#endif //_GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct char_traits + { + typedef char8_t char_type; + typedef unsigned int int_type; +#if _GLIBCXX_HOSTED + typedef u8streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::length(__s); +#endif + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + +#if _GLIBCXX_HOSTED + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(-1); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } +#endif // HOSTED + }; +#endif //_GLIBCXX_USE_CHAR8_T + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + struct char_traits + { + typedef char16_t char_type; +#ifdef __UINT_LEAST16_TYPE__ + typedef __UINT_LEAST16_TYPE__ int_type; +#else + typedef uint_least16_t int_type; +#endif +#if _GLIBCXX_HOSTED + typedef streamoff off_type; + typedef u16streampos pos_type; + typedef mbstate_t state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + +#if _GLIBCXX_HOSTED + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return __c == eof() ? int_type(0xfffd) : int_type(__c); } + + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } +#else // !HOSTED + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return int_type(__c); } +#endif // !HOSTED + }; + + template<> + struct char_traits + { + typedef char32_t char_type; +#ifdef __UINT_LEAST32_TYPE__ + typedef __UINT_LEAST32_TYPE__ int_type; +#else + typedef uint_least32_t int_type; +#endif +#if _GLIBCXX_HOSTED + typedef streamoff off_type; + typedef u32streampos pos_type; + typedef mbstate_t state_type; +#endif // HOSTED +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { +#if __cpp_constexpr_dynamic_alloc + if (std::__is_constant_evaluated()) + std::construct_at(__builtin_addressof(__c1), __c2); + else +#endif + __c1 = __c2; + } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#if __cplusplus >= 202002L + if (std::__is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return int_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + +#if _GLIBCXX_HOSTED + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } +#endif // HOSTED + }; + +#if __cpp_lib_three_way_comparison + namespace __detail + { + template + constexpr auto + __char_traits_cmp_cat(int __cmp) noexcept + { + if constexpr (requires { typename _ChTraits::comparison_category; }) + { + using _Cat = typename _ChTraits::comparison_category; + static_assert( !is_void_v> ); + return static_cast<_Cat>(__cmp <=> 0); + } + else + return static_cast(__cmp <=> 0); + } + } // namespace __detail +#endif // C++20 + +#pragma GCC diagnostic pop + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _CHAR_TRAITS_H diff --git a/template/sysroot/include/bits/concept_check.h b/template/sysroot/include/bits/concept_check.h new file mode 100644 index 0000000..65f662b --- /dev/null +++ b/template/sysroot/include/bits/concept_check.h @@ -0,0 +1,81 @@ +// Concept-checking control -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _CONCEPT_CHECK_H +#define _CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include + +// All places in libstdc++-v3 where these are used, or /might/ be used, or +// don't need to be used, or perhaps /should/ be used, are commented with +// "concept requirements" (and maybe some more text). So grep like crazy +// if you're looking for additional places to use these. + +// Concept-checking code is off by default unless users turn it on via +// configure options or editing c++config.h. +// It is not supported for freestanding implementations. + +#if !defined(_GLIBCXX_CONCEPT_CHECKS) + +#define __glibcxx_function_requires(...) +#define __glibcxx_class_requires(_a,_b) +#define __glibcxx_class_requires2(_a,_b,_c) +#define __glibcxx_class_requires3(_a,_b,_c,_d) +#define __glibcxx_class_requires4(_a,_b,_c,_d,_e) + +#else // the checks are on + +#include + +// Note that the obvious and elegant approach of +// +//#define glibcxx_function_requires(C) debug::function_requires< debug::C >() +// +// won't work due to concept templates with more than one parameter, e.g., +// BinaryPredicateConcept. The preprocessor tries to split things up on +// the commas in the template argument list. We can't use an inner pair of +// parenthesis to hide the commas, because "debug::(Temp)" isn't +// a valid instantiation pattern. Thus, we steal a feature from C99. + +#define __glibcxx_function_requires(...) \ + __gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >(); +#define __glibcxx_class_requires(_a,_C) \ + _GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C); +#define __glibcxx_class_requires2(_a,_b,_C) \ + _GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C); +#define __glibcxx_class_requires3(_a,_b,_c,_C) \ + _GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C); +#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \ + _GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C); + +#endif // enable/disable + +#endif // _GLIBCXX_CONCEPT_CHECK diff --git a/template/sysroot/include/bits/cpp_type_traits.h b/template/sysroot/include/bits/cpp_type_traits.h new file mode 100644 index 0000000..59f1a18 --- /dev/null +++ b/template/sysroot/include/bits/cpp_type_traits.h @@ -0,0 +1,614 @@ +// The -*- C++ -*- type traits classes for internal use in libstdc++ + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cpp_type_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/type_traits} + */ + +// Written by Gabriel Dos Reis + +#ifndef _CPP_TYPE_TRAITS_H +#define _CPP_TYPE_TRAITS_H 1 + +#pragma GCC system_header + +#include + +// +// This file provides some compile-time information about various types. +// These representations were designed, on purpose, to be constant-expressions +// and not types as found in . In particular, they +// can be used in control structures and the optimizer hopefully will do +// the obvious thing. +// +// Why integral expressions, and not functions nor types? +// Firstly, these compile-time entities are used as template-arguments +// so function return values won't work: We need compile-time entities. +// We're left with types and constant integral expressions. +// Secondly, from the point of view of ease of use, type-based compile-time +// information is -not- *that* convenient. One has to write lots of +// overloaded functions and to hope that the compiler will select the right +// one. As a net effect, the overall structure isn't very clear at first +// glance. +// Thirdly, partial ordering and overload resolution (of function templates) +// is highly costly in terms of compiler-resource. It is a Good Thing to +// keep these resource consumption as least as possible. +// +// See valarray_array.h for a case use. +// +// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. +// +// Update 2005: types are also provided and has been +// removed. +// + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __true_type { }; + struct __false_type { }; + + template + struct __truth_type + { typedef __false_type __type; }; + + template<> + struct __truth_type + { typedef __true_type __type; }; + + // N.B. The conversions to bool are needed due to the issue + // explained in c++/19404. + template + struct __traitor + { + enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; + typedef typename __truth_type<__value>::__type __type; + }; + + // Compare for equality of types. + template + struct __are_same + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __are_same<_Tp, _Tp> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // Holds if the template-argument is a void type. + template + struct __is_void + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_void + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // Integer types + // + template + struct __is_integer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Thirteen specializations (yes there are eleven standard integer + // types; long long and unsigned long long are + // supported as extensions). Up to four target-specific __int + // types are supported as well. + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +# ifdef __WCHAR_TYPE__ + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +# endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#if __cplusplus >= 201103L + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#define __INT_N(TYPE) \ + __extension__ \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; \ + __extension__ \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; + +#ifdef __GLIBCXX_TYPE_INT_N_0 +__INT_N(__GLIBCXX_TYPE_INT_N_0) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 +__INT_N(__GLIBCXX_TYPE_INT_N_1) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 +__INT_N(__GLIBCXX_TYPE_INT_N_2) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 +__INT_N(__GLIBCXX_TYPE_INT_N_3) +#endif + +#undef __INT_N + + // + // Floating point types + // + template + struct __is_floating + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // three specializations (float, double and 'long double') + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __is_floating<_Float16> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __is_floating<_Float32> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __is_floating<_Float64> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __is_floating<_Float128> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __is_floating<__gnu_cxx::__bfloat16_t> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + // + // Pointer types + // + template + struct __is_pointer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __is_pointer<_Tp*> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // An arithmetic type is an integer type or a floating point type + // + template + struct __is_arithmetic + : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > + { }; + + // + // A scalar type is an arithmetic type or a pointer type + // + template + struct __is_scalar + : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > + { }; + + // + // For use in std::copy and std::find overloads for streambuf iterators. + // + template + struct __is_char + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#ifdef __WCHAR_TYPE__ + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template + struct __is_byte + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#if __cplusplus >= 201703L + enum class byte : unsigned char; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif // C++17 + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template struct iterator_traits; + + // A type that is safe for use with memcpy, memmove, memcmp etc. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = __is_trivially_copyable(_Tp) }; + }; + + // Cannot use memcpy/memmove/memcmp on volatile types even if they are + // trivially copyable, so ensure __memcpyable + // and similar will be false. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = 0 }; + }; + + // Whether two iterator types can be used with memcpy/memmove. + template + struct __memcpyable + { + enum { __value = 0 }; + }; + + template + struct __memcpyable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcpyable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether two iterator types can be used with memcmp. + // This trait only says it's well-formed to use memcmp, not that it + // gives the right answer for a given algorithm. So for example, std::equal + // needs to add additional checks that the types are integers or pointers, + // because other trivially copyable types can overload operator==. + template + struct __memcmpable + { + enum { __value = 0 }; + }; + + // OK to use memcmp with pointers to trivially copyable types. + template + struct __memcmpable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether memcmp can be used to determine ordering for a type + // e.g. in std::lexicographical_compare or three-way comparisons. + // True for unsigned integer-like types where comparing each byte in turn + // as an unsigned char yields the right result. This is true for all + // unsigned integers on big endian targets, but only unsigned narrow + // character types (and std::byte) on little endian targets. + template::__value +#else + __is_byte<_Tp>::__value +#endif + > + struct __is_memcmp_ordered + { + static const bool __value = _Tp(-1) > _Tp(1); // is unsigned + }; + + template + struct __is_memcmp_ordered<_Tp, false> + { + static const bool __value = false; + }; + + // Whether two types can be compared using memcmp. + template + struct __is_memcmp_ordered_with + { + static const bool __value = __is_memcmp_ordered<_Tp>::__value + && __is_memcmp_ordered<_Up>::__value; + }; + + template + struct __is_memcmp_ordered_with<_Tp, _Up, false> + { + static const bool __value = false; + }; + +#if __cplusplus >= 201703L +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // std::byte is not an integer, but it can be compared using memcmp. + template<> + struct __is_memcmp_ordered + { static constexpr bool __value = true; }; +#endif + + // std::byte can only be compared to itself, not to other types. + template<> + struct __is_memcmp_ordered_with + { static constexpr bool __value = true; }; + + template + struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize> + { static constexpr bool __value = false; }; + + template + struct __is_memcmp_ordered_with + { static constexpr bool __value = false; }; +#endif + + // + // Move iterator type + // + template + struct __is_move_iterator + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the move_iterator wrapper. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __miter_base(_Iterator __it) + { return __it; } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif //_CPP_TYPE_TRAITS_H diff --git a/template/sysroot/include/bits/cpu_defines.h b/template/sysroot/include/bits/cpu_defines.h new file mode 100644 index 0000000..e0c5a79 --- /dev/null +++ b/template/sysroot/include/bits/cpu_defines.h @@ -0,0 +1,33 @@ +// Specific definitions for generic platforms -*- C++ -*- + +// Copyright (C) 2005-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cpu_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _GLIBCXX_CPU_DEFINES +#define _GLIBCXX_CPU_DEFINES 1 + +#endif diff --git a/template/sysroot/include/bits/ctype_base.h b/template/sysroot/include/bits/ctype_base.h new file mode 100644 index 0000000..7432832 --- /dev/null +++ b/template/sysroot/include/bits/ctype_base.h @@ -0,0 +1,59 @@ +// Locale support -*- C++ -*- + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882: 22.1 Locales +// + +// Default information, may not be appropriate for specific host. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @brief Base class for ctype. + struct ctype_base + { + // Non-standard typedefs. + typedef const int* __to_type; + + // NB: Offsets into ctype::_M_table force a particular size + // on the mask type. Because of this, we don't use an enum. + typedef unsigned int mask; + static const mask upper = 1 << 0; + static const mask lower = 1 << 1; + static const mask alpha = 1 << 2; + static const mask digit = 1 << 3; + static const mask xdigit = 1 << 4; + static const mask space = 1 << 5; + static const mask print = 1 << 6; + static const mask graph = (1 << 2) | (1 << 3) | (1 << 9); // alnum|punct + static const mask cntrl = 1 << 8; + static const mask punct = 1 << 9; + static const mask alnum = (1 << 2) | (1 << 3); // alpha|digit + static const mask blank = 1 << 10; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/template/sysroot/include/bits/ctype_inline.h b/template/sysroot/include/bits/ctype_inline.h new file mode 100644 index 0000000..74481c2 --- /dev/null +++ b/template/sysroot/include/bits/ctype_inline.h @@ -0,0 +1,173 @@ +// Locale support -*- C++ -*- + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ctype_inline.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.1 Locales +// + +// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*) +// functions go in ctype.cc + +// The following definitions are portable, but insanely slow. If one +// cares at all about performance, then specialized ctype +// functionality should be added for the native os in question: see +// the config/os/bits/ctype_*.h files. + +// Constructing a synthetic "C" table should be seriously considered... + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + bool + ctype:: + is(mask __m, char __c) const + { + if (_M_table) + return _M_table[static_cast(__c)] & __m; + else + { + bool __ret = false; + const size_t __bitmasksize = 15; + size_t __bitcur = 0; // Lowest bitmask in ctype_base == 0 + for (; __bitcur <= __bitmasksize; ++__bitcur) + { + const mask __bit = static_cast(1 << __bitcur); + if (__m & __bit) + { + bool __testis; + switch (__bit) + { + case space: + __testis = isspace(__c); + break; + case print: + __testis = isprint(__c); + break; + case cntrl: + __testis = iscntrl(__c); + break; + case upper: + __testis = isupper(__c); + break; + case lower: + __testis = islower(__c); + break; + case alpha: + __testis = isalpha(__c); + break; + case digit: + __testis = isdigit(__c); + break; + case punct: + __testis = ispunct(__c); + break; + case xdigit: + __testis = isxdigit(__c); + break; + case alnum: + __testis = isalnum(__c); + break; + case graph: + __testis = isgraph(__c); + break; +#ifdef _GLIBCXX_USE_C99_CTYPE_TR1 + case blank: + __testis = isblank(__c); + break; +#endif + default: + __testis = false; + break; + } + __ret |= __testis; + } + } + return __ret; + } + } + + const char* + ctype:: + is(const char* __low, const char* __high, mask* __vec) const + { + if (_M_table) + while (__low < __high) + *__vec++ = _M_table[static_cast(*__low++)]; + else + { + // Highest bitmask in ctype_base == 11. + const size_t __bitmasksize = 15; + for (;__low < __high; ++__vec, ++__low) + { + mask __m = 0; + // Lowest bitmask in ctype_base == 0 + size_t __i = 0; + for (;__i <= __bitmasksize; ++__i) + { + const mask __bit = static_cast(1 << __i); + if (this->is(__bit, *__low)) + __m |= __bit; + } + *__vec = __m; + } + } + return __high; + } + + const char* + ctype:: + scan_is(mask __m, const char* __low, const char* __high) const + { + if (_M_table) + while (__low < __high + && !(_M_table[static_cast(*__low)] & __m)) + ++__low; + else + while (__low < __high && !this->is(__m, *__low)) + ++__low; + return __low; + } + + const char* + ctype:: + scan_not(mask __m, const char* __low, const char* __high) const + { + if (_M_table) + while (__low < __high + && (_M_table[static_cast(*__low)] & __m) != 0) + ++__low; + else + while (__low < __high && this->is(__m, *__low) != 0) + ++__low; + return __low; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/template/sysroot/include/bits/cxxabi_forced.h b/template/sysroot/include/bits/cxxabi_forced.h new file mode 100644 index 0000000..5759a89 --- /dev/null +++ b/template/sysroot/include/bits/cxxabi_forced.h @@ -0,0 +1,60 @@ +// cxxabi.h subset for cancellation -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_forced.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cxxabi.h} + */ + +#ifndef _CXXABI_FORCED_H +#define _CXXABI_FORCED_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#ifdef __cplusplus +namespace __cxxabiv1 +{ + /** + * @brief Thrown as part of forced unwinding. + * @ingroup exceptions + * + * A magic placeholder class that can be caught by reference to + * recognize forced unwinding. + */ + class __forced_unwind + { + virtual ~__forced_unwind() throw(); + + // Prevent catch by value. + virtual void __pure_dummy() = 0; + }; +} +#endif // __cplusplus + +#pragma GCC visibility pop + +#endif // __CXXABI_FORCED_H diff --git a/template/sysroot/include/bits/cxxabi_init_exception.h b/template/sysroot/include/bits/cxxabi_init_exception.h new file mode 100644 index 0000000..cbb3ce3 --- /dev/null +++ b/template/sysroot/include/bits/cxxabi_init_exception.h @@ -0,0 +1,81 @@ +// ABI Support -*- C++ -*- + +// Copyright (C) 2016-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_init_exception.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _CXXABI_INIT_EXCEPTION_H +#define _CXXABI_INIT_EXCEPTION_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#include +#include + +#ifndef _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_HAVE_CDTOR_CALLABI 0 +#else +#define _GLIBCXX_HAVE_CDTOR_CALLABI 1 +#endif + +#ifdef __cplusplus + +namespace std +{ + class type_info; +} + +namespace __cxxabiv1 +{ + struct __cxa_refcounted_exception; + + extern "C" + { + // Allocate memory for the primary exception plus the thrown object. + void* + __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW; + + void + __cxa_free_exception(void*) _GLIBCXX_NOTHROW; + + // Initialize exception (this is a GNU extension) + __cxa_refcounted_exception* + __cxa_init_primary_exception(void *__object, std::type_info *__tinfo, + void (_GLIBCXX_CDTOR_CALLABI *__dest) (void *)) + _GLIBCXX_NOTHROW; + + } +} // namespace __cxxabiv1 + +#endif + +#pragma GCC visibility pop + +#endif // _CXXABI_INIT_EXCEPTION_H diff --git a/template/sysroot/include/bits/cxxabi_tweaks.h b/template/sysroot/include/bits/cxxabi_tweaks.h new file mode 100644 index 0000000..1eff23d --- /dev/null +++ b/template/sysroot/include/bits/cxxabi_tweaks.h @@ -0,0 +1,59 @@ +// Control various target specific ABI tweaks. Generic version. + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_tweaks.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cxxabi.h} + */ + +#ifndef _CXXABI_TWEAKS_H +#define _CXXABI_TWEAKS_H 1 + +#ifdef __cplusplus +namespace __cxxabiv1 +{ + extern "C" + { +#endif + + // The generic ABI uses the first byte of a 64-bit guard variable. +#define _GLIBCXX_GUARD_TEST(x) (*(char *) (x) != 0) +#define _GLIBCXX_GUARD_SET(x) *(char *) (x) = 1 +#define _GLIBCXX_GUARD_BIT __guard_test_bit (0, 1) +#define _GLIBCXX_GUARD_PENDING_BIT __guard_test_bit (1, 1) +#define _GLIBCXX_GUARD_WAITING_BIT __guard_test_bit (2, 1) + __extension__ typedef int __guard __attribute__((mode (__DI__))); + + // __cxa_vec_ctor has void return type. + typedef void __cxa_vec_ctor_return_type; +#define _GLIBCXX_CXA_VEC_CTOR_RETURN(x) return + // Constructors and destructors do not return a value. + typedef void __cxa_cdtor_return_type; + +#ifdef __cplusplus + } +} // namespace __cxxabiv1 +#endif + +#endif diff --git a/template/sysroot/include/bits/elements_of.h b/template/sysroot/include/bits/elements_of.h new file mode 100644 index 0000000..2c65f25 --- /dev/null +++ b/template/sysroot/include/bits/elements_of.h @@ -0,0 +1,72 @@ +// Tag type for yielding ranges rather than values in -*- C++ -*- + +// Copyright (C) 2023-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#ifndef _GLIBCXX_BITS_ELEMENTS_OF +#define _GLIBCXX_BITS_ELEMENTS_OF + +#pragma GCC system_header + +#include + +#include + +// C++ >= 23 && __glibcxx_coroutine +#if defined(__glibcxx_ranges) && defined(__glibcxx_generator) +#include +#include + +#if _GLIBCXX_HOSTED +# include // likely desirable if hosted. +#endif // HOSTED + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + + /** + * @ingroup ranges + * @since C++23 + * @{ + */ + + template> + struct elements_of + { + [[no_unique_address]] _Range range; + [[no_unique_address]] _Alloc allocator = _Alloc(); + }; + + template> + elements_of(_Range&&, _Alloc = _Alloc()) + -> elements_of<_Range&&, _Alloc>; + + /// @} +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __glibcxx_generator && __glibcxx_ranges +#endif // _GLIBCXX_BITS_ELEMENTS_OF diff --git a/template/sysroot/include/bits/enable_special_members.h b/template/sysroot/include/bits/enable_special_members.h new file mode 100644 index 0000000..73a9b02 --- /dev/null +++ b/template/sysroot/include/bits/enable_special_members.h @@ -0,0 +1,316 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/enable_special_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _ENABLE_SPECIAL_MEMBERS_H +#define _ENABLE_SPECIAL_MEMBERS_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +/// @cond undocumented + + struct _Enable_default_constructor_tag + { + explicit constexpr _Enable_default_constructor_tag() = default; + }; + +/** + * @brief A mixin helper to conditionally enable or disable the default + * constructor. + * @sa _Enable_special_members + */ +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + + +/** + * @brief A mixin helper to conditionally enable or disable the default + * destructor. + * @sa _Enable_special_members + */ +template + struct _Enable_destructor { }; + +/** + * @brief A mixin helper to conditionally enable or disable the copy/move + * special members. + * @sa _Enable_special_members + */ +template + struct _Enable_copy_move { }; + +/** + * @brief A mixin helper to conditionally enable or disable the special + * members. + * + * The @c _Tag type parameter is to make mixin bases unique and thus avoid + * ambiguities. + */ +template + struct _Enable_special_members + : private _Enable_default_constructor<_Default, _Tag>, + private _Enable_destructor<_Destructor, _Tag>, + private _Enable_copy_move<_Copy, _CopyAssignment, + _Move, _MoveAssignment, + _Tag> + { }; + +// Boilerplate follows. + +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = delete; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + +template + struct _Enable_destructor + { ~_Enable_destructor() noexcept = delete; }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +/// @endcond +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _ENABLE_SPECIAL_MEMBERS_H diff --git a/template/sysroot/include/bits/error_constants.h b/template/sysroot/include/bits/error_constants.h new file mode 100644 index 0000000..2038914 --- /dev/null +++ b/template/sysroot/include/bits/error_constants.h @@ -0,0 +1,180 @@ +// Specific definitions for generic platforms -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/error_constants.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{system_error} + */ + +#ifndef _GLIBCXX_ERROR_CONSTANTS +#define _GLIBCXX_ERROR_CONSTANTS 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + enum class errc + { + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + +#ifdef EBADMSG + bad_message = EBADMSG, +#endif + + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + +#ifdef EIDRM + identifier_removed = EIDRM, +#endif + + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + +#ifdef ENOLINK + no_link = ENOLINK, +#endif + + no_lock_available = ENOLCK, + +#ifdef ENODATA + no_message_available = ENODATA, +#endif + + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, + +#ifdef ENOSR + no_stream_resources = ENOSR, +#endif + + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, + +#ifdef ENOSTR + not_a_stream = ENOSTR, +#endif + + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + +#ifdef ENOTSUP + not_supported = ENOTSUP, +#endif + +#ifdef ECANCELED + operation_canceled = ECANCELED, +#endif + + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#endif + + permission_denied = EACCES, + +#ifdef EPROTO + protocol_error = EPROTO, +#endif + + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#endif + +#ifdef ETIME + stream_timeout = ETIME, +#endif + +#ifdef ETXTBSY + text_file_busy = ETXTBSY, +#endif + + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + +#ifdef EOVERFLOW + value_too_large = EOVERFLOW, +#elif defined __AVR__ + value_too_large = 999, +#endif + + wrong_protocol_type = EPROTOTYPE + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/exception.h b/template/sysroot/include/bits/exception.h new file mode 100644 index 0000000..dca5882 --- /dev/null +++ b/template/sysroot/include/bits/exception.h @@ -0,0 +1,83 @@ +// Exception Handling support header for -*- C++ -*- + +// Copyright (C) 2016-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/exception.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef __EXCEPTION_H +#define __EXCEPTION_H 1 + +#pragma GCC system_header + +#include + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ + /** + * @defgroup exceptions Exceptions + * @ingroup diagnostics + * @since C++98 + * + * Classes and functions for reporting errors via exceptions. + * @{ + */ + + /** + * @brief Base class for all library exceptions. + * + * This is the base class for all exceptions thrown by the standard + * library, and by certain language expressions. You are free to derive + * your own %exception classes, or use a different hierarchy, or to + * throw non-class data (e.g., fundamental types). + */ + class exception + { + public: + exception() _GLIBCXX_NOTHROW { } + virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW; +#if __cplusplus >= 201103L + exception(const exception&) = default; + exception& operator=(const exception&) = default; + exception(exception&&) = default; + exception& operator=(exception&&) = default; +#endif + + /** Returns a C-style character string describing the general cause + * of the current error. */ + virtual const char* + what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW; + }; + + /// @} + +} // namespace std + +} + +#endif diff --git a/template/sysroot/include/bits/exception_defines.h b/template/sysroot/include/bits/exception_defines.h new file mode 100644 index 0000000..c771270 --- /dev/null +++ b/template/sysroot/include/bits/exception_defines.h @@ -0,0 +1,45 @@ +// -fno-exceptions Support -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/exception_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + */ + +#ifndef _EXCEPTION_DEFINES_H +#define _EXCEPTION_DEFINES_H 1 + +#if ! __cpp_exceptions +// Iff -fno-exceptions, transform error handling code to work without it. +# define __try if (true) +# define __catch(X) if (false) +# define __throw_exception_again +#else +// Else proceed normally. +# define __try try +# define __catch(X) catch(X) +# define __throw_exception_again throw +#endif + +#endif diff --git a/template/sysroot/include/bits/exception_ptr.h b/template/sysroot/include/bits/exception_ptr.h new file mode 100644 index 0000000..7c234ce --- /dev/null +++ b/template/sysroot/include/bits/exception_ptr.h @@ -0,0 +1,295 @@ +// Exception Handling support header (exception_ptr class) for -*- C++ -*- + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/exception_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + */ + +#ifndef _EXCEPTION_PTR_H +#define _EXCEPTION_PTR_H + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +#endif + +#ifdef _GLIBCXX_EH_PTR_RELOPS_COMPAT +# define _GLIBCXX_EH_PTR_USED __attribute__((__used__)) +#else +# define _GLIBCXX_EH_PTR_USED +#endif + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ + class type_info; + + /** + * @addtogroup exceptions + * @{ + */ + + namespace __exception_ptr + { + class exception_ptr; + } + + using __exception_ptr::exception_ptr; + + /** Obtain an exception_ptr to the currently handled exception. + * + * If there is none, or the currently handled exception is foreign, + * return the null value. + * + * @since C++11 + */ + exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT; + + template + exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT; + + /// Throw the object pointed to by the exception_ptr. + void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__)); + + namespace __exception_ptr + { + using std::rethrow_exception; // So that ADL finds it. + + /** + * @brief An opaque pointer to an arbitrary exception. + * + * The actual name of this type is unspecified, so the alias + * `std::exception_ptr` should be used to refer to it. + * + * @headerfile exception + * @since C++11 (but usable in C++98 as a GCC extension) + * @ingroup exceptions + */ + class exception_ptr + { + void* _M_exception_object; + + explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT; + + void _M_addref() _GLIBCXX_USE_NOEXCEPT; + void _M_release() _GLIBCXX_USE_NOEXCEPT; + + void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__)); + + friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT; + friend void std::rethrow_exception(exception_ptr); + template + friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT; + + public: + exception_ptr() _GLIBCXX_USE_NOEXCEPT; + + exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT; + +#if __cplusplus >= 201103L + exception_ptr(nullptr_t) noexcept + : _M_exception_object(nullptr) + { } + + exception_ptr(exception_ptr&& __o) noexcept + : _M_exception_object(__o._M_exception_object) + { __o._M_exception_object = nullptr; } +#endif + +#if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT) + typedef void (exception_ptr::*__safe_bool)(); + + // For construction from nullptr or 0. + exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT; +#endif + + exception_ptr& + operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT; + +#if __cplusplus >= 201103L + exception_ptr& + operator=(exception_ptr&& __o) noexcept + { + exception_ptr(static_cast(__o)).swap(*this); + return *this; + } +#endif + + ~exception_ptr() _GLIBCXX_USE_NOEXCEPT; + + void + swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT; + +#ifdef _GLIBCXX_EH_PTR_COMPAT + // Retained for compatibility with CXXABI_1.3. + void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT + __attribute__ ((__const__)); + bool operator!() const _GLIBCXX_USE_NOEXCEPT + __attribute__ ((__pure__)); + operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT; +#endif + +#if __cplusplus >= 201103L + explicit operator bool() const noexcept + { return _M_exception_object; } +#endif + +#if __cpp_impl_three_way_comparison >= 201907L \ + && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT + friend bool + operator==(const exception_ptr&, const exception_ptr&) noexcept = default; +#else + friend _GLIBCXX_EH_PTR_USED bool + operator==(const exception_ptr& __x, const exception_ptr& __y) + _GLIBCXX_USE_NOEXCEPT + { return __x._M_exception_object == __y._M_exception_object; } + + friend _GLIBCXX_EH_PTR_USED bool + operator!=(const exception_ptr& __x, const exception_ptr& __y) + _GLIBCXX_USE_NOEXCEPT + { return __x._M_exception_object != __y._M_exception_object; } +#endif + + const class std::type_info* + __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT + __attribute__ ((__pure__)); + }; + + _GLIBCXX_EH_PTR_USED + inline + exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT + : _M_exception_object(0) + { } + + _GLIBCXX_EH_PTR_USED + inline + exception_ptr::exception_ptr(const exception_ptr& __other) + _GLIBCXX_USE_NOEXCEPT + : _M_exception_object(__other._M_exception_object) + { + if (_M_exception_object) + _M_addref(); + } + + _GLIBCXX_EH_PTR_USED + inline + exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT + { + if (_M_exception_object) + _M_release(); + } + + _GLIBCXX_EH_PTR_USED + inline exception_ptr& + exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT + { + exception_ptr(__other).swap(*this); + return *this; + } + + _GLIBCXX_EH_PTR_USED + inline void + exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT + { + void *__tmp = _M_exception_object; + _M_exception_object = __other._M_exception_object; + __other._M_exception_object = __tmp; + } + + /// @relates exception_ptr + inline void + swap(exception_ptr& __lhs, exception_ptr& __rhs) + { __lhs.swap(__rhs); } + + /// @cond undocumented + template + _GLIBCXX_CDTOR_CALLABI + inline void + __dest_thunk(void* __x) + { static_cast<_Ex*>(__x)->~_Ex(); } + /// @endcond + + } // namespace __exception_ptr + + using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it. + + /// Obtain an exception_ptr pointing to a copy of the supplied object. +#if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions + template + exception_ptr + make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT + { +#if __cplusplus >= 201103L && __cpp_rtti + using _Ex2 = typename decay<_Ex>::type; + void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex)); + (void) __cxxabiv1::__cxa_init_primary_exception( + __e, const_cast(&typeid(_Ex)), + __exception_ptr::__dest_thunk<_Ex2>); + __try + { + ::new (__e) _Ex2(__ex); + return exception_ptr(__e); + } + __catch(...) + { + __cxxabiv1::__cxa_free_exception(__e); + return current_exception(); + } +#else + try + { + throw __ex; + } + catch(...) + { + return current_exception(); + } +#endif + } +#else // no RTTI and no exceptions + // This is always_inline so the linker will never use this useless definition + // instead of a working one compiled with RTTI and/or exceptions enabled. + template + __attribute__ ((__always_inline__)) + inline exception_ptr + make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT + { return exception_ptr(); } +#endif + +#undef _GLIBCXX_EH_PTR_USED + + /// @} group exceptions +} // namespace std + +} // extern "C++" + +#endif diff --git a/template/sysroot/include/bits/extc++.h b/template/sysroot/include/bits/extc++.h new file mode 100644 index 0000000..651b9da --- /dev/null +++ b/template/sysroot/include/bits/extc++.h @@ -0,0 +1,86 @@ +// C++ includes used for precompiling extensions -*- C++ -*- + +// Copyright (C) 2006-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file extc++.h + * This is an implementation file for a precompiled header. + */ + +#if __cplusplus < 201103L +#include +#else +#include +#endif + +#if __cplusplus >= 201103L +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if _GLIBCXX_HOSTED +#include +#include +#if __cplusplus >= 201103L +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus >= 201103L +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_HAVE_ICONV + #include + #include +#endif +#endif // HOSTED diff --git a/template/sysroot/include/bits/functexcept.h b/template/sysroot/include/bits/functexcept.h new file mode 100644 index 0000000..671c856 --- /dev/null +++ b/template/sysroot/include/bits/functexcept.h @@ -0,0 +1,143 @@ +// Function-Based Exception Support -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functexcept.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + * + * This header provides support for -fno-exceptions. + */ + +// +// ISO C++ 14882: 19.1 Exception classes +// + +#ifndef _FUNCTEXCEPT_H +#define _FUNCTEXCEPT_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if _GLIBCXX_HOSTED + // Helper for exception objects in + void + __throw_bad_exception(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_alloc(void) __attribute__((__noreturn__)); + + void + __throw_bad_array_new_length(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_cast(void) __attribute__((__noreturn__,__cold__)); + + void + __throw_bad_typeid(void) __attribute__((__noreturn__,__cold__)); + + // Helpers for exception objects in + void + __throw_logic_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_domain_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_invalid_argument(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_length_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_out_of_range(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__,__cold__)) + __attribute__((__format__(__gnu_printf__, 1, 2))); + + void + __throw_runtime_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_range_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_overflow_error(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_underflow_error(const char*) __attribute__((__noreturn__,__cold__)); + + // Helpers for exception objects in + void + __throw_ios_failure(const char*) __attribute__((__noreturn__,__cold__)); + + void + __throw_ios_failure(const char*, int) __attribute__((__noreturn__,__cold__)); + + // Helpers for exception objects in + void + __throw_system_error(int) __attribute__((__noreturn__,__cold__)); + + // Helpers for exception objects in + void + __throw_future_error(int) __attribute__((__noreturn__,__cold__)); + + // Helpers for exception objects in + void + __throw_bad_function_call() __attribute__((__noreturn__,__cold__)); + +#else // ! HOSTED + + __attribute__((__noreturn__)) inline void + __throw_invalid_argument(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_out_of_range(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_out_of_range_fmt(const char*, ...) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_runtime_error(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_overflow_error(const char*) + { std::__terminate(); } + +#endif // HOSTED + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/functional_hash.h b/template/sysroot/include/bits/functional_hash.h new file mode 100644 index 0000000..3626ebe --- /dev/null +++ b/template/sysroot/include/bits/functional_hash.h @@ -0,0 +1,305 @@ +// functional_hash.h header -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functional_hash.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _FUNCTIONAL_HASH_H +#define _FUNCTIONAL_HASH_H 1 + +#pragma GCC system_header + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup hashes Hashes + * @ingroup functors + * + * Hashing functors taking a variable type and returning a @c std::size_t. + * + * @{ + */ + + template + struct __hash_base + { + typedef _Result result_type _GLIBCXX17_DEPRECATED; + typedef _Arg argument_type _GLIBCXX17_DEPRECATED; + }; + + /// Primary class template hash. + template + struct hash; + + template + struct __poison_hash + { + static constexpr bool __enable_hash_call = false; + private: + // Private rather than deleted to be non-trivially-copyable. + __poison_hash(__poison_hash&&); + ~__poison_hash(); + }; + + template + struct __poison_hash<_Tp, __void_t()(declval<_Tp>()))>> + { + static constexpr bool __enable_hash_call = true; + }; + + // Helper struct for SFINAE-poisoning non-enum types. + template::value> + struct __hash_enum + { + private: + // Private rather than deleted to be non-trivially-copyable. + __hash_enum(__hash_enum&&); + ~__hash_enum(); + }; + + // Helper struct for hash with enum types. + template + struct __hash_enum<_Tp, true> : public __hash_base + { + size_t + operator()(_Tp __val) const noexcept + { + using __type = typename underlying_type<_Tp>::type; + return hash<__type>{}(static_cast<__type>(__val)); + } + }; + + /// Primary class template hash, usable for enum types only. + // Use with non-enum types still SFINAES. + template + struct hash : __hash_enum<_Tp> + { }; + + /// Partial specializations for pointer types. + template + struct hash<_Tp*> : public __hash_base + { + size_t + operator()(_Tp* __p) const noexcept + { return reinterpret_cast(__p); } + }; + + // Explicit specializations for integer types. +#define _Cxx_hashtable_define_trivial_hash(_Tp) \ + template<> \ + struct hash<_Tp> : public __hash_base \ + { \ + size_t \ + operator()(_Tp __val) const noexcept \ + { return static_cast(__val); } \ + }; + + /// Explicit specialization for bool. + _Cxx_hashtable_define_trivial_hash(bool) + + /// Explicit specialization for char. + _Cxx_hashtable_define_trivial_hash(char) + + /// Explicit specialization for signed char. + _Cxx_hashtable_define_trivial_hash(signed char) + + /// Explicit specialization for unsigned char. + _Cxx_hashtable_define_trivial_hash(unsigned char) + + /// Explicit specialization for wchar_t. + _Cxx_hashtable_define_trivial_hash(wchar_t) + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + _Cxx_hashtable_define_trivial_hash(char8_t) +#endif + + /// Explicit specialization for char16_t. + _Cxx_hashtable_define_trivial_hash(char16_t) + + /// Explicit specialization for char32_t. + _Cxx_hashtable_define_trivial_hash(char32_t) + + /// Explicit specialization for short. + _Cxx_hashtable_define_trivial_hash(short) + + /// Explicit specialization for int. + _Cxx_hashtable_define_trivial_hash(int) + + /// Explicit specialization for long. + _Cxx_hashtable_define_trivial_hash(long) + + /// Explicit specialization for long long. + _Cxx_hashtable_define_trivial_hash(long long) + + /// Explicit specialization for unsigned short. + _Cxx_hashtable_define_trivial_hash(unsigned short) + + /// Explicit specialization for unsigned int. + _Cxx_hashtable_define_trivial_hash(unsigned int) + + /// Explicit specialization for unsigned long. + _Cxx_hashtable_define_trivial_hash(unsigned long) + + /// Explicit specialization for unsigned long long. + _Cxx_hashtable_define_trivial_hash(unsigned long long) + +#ifdef __GLIBCXX_TYPE_INT_N_0 + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0) + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1) + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2) + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3) + __extension__ + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned) +#endif + +#undef _Cxx_hashtable_define_trivial_hash + + struct _Hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(0xc70f6907UL)) + { return _Hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + // A hash function similar to FNV-1a (see PR59406 for how it differs). + struct _Fnv_hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(2166136261UL)) + { return _Fnv_hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + /// Specialization for float. + template<> + struct hash : public __hash_base + { + size_t + operator()(float __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; + } + }; + + /// Specialization for double. + template<> + struct hash : public __hash_base + { + size_t + operator()(double __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; + } + }; + + /// Specialization for long double. + template<> + struct hash + : public __hash_base + { + _GLIBCXX_PURE size_t + operator()(long double __val) const noexcept; + }; + +#if __cplusplus >= 201703L + template<> + struct hash : public __hash_base + { + size_t + operator()(nullptr_t) const noexcept + { return 0; } + }; +#endif + + /// @} group hashes + + /** Hint about performance of hash functions. + * + * If a given hash function object is not fast, the hash-based containers + * will cache the hash code. + * The default behavior is to consider that hashers are fast unless specified + * otherwise. + * + * Users can specialize this for their own hash functions in order to force + * caching of hash codes in unordered containers. Specializing this trait + * affects the ABI of the unordered containers, so use it carefully. + */ + template + struct __is_fast_hash : public std::true_type + { }; + + template<> + struct __is_fast_hash> : public std::false_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // _FUNCTIONAL_HASH_H diff --git a/template/sysroot/include/bits/gthr-default.h b/template/sysroot/include/bits/gthr-default.h new file mode 100644 index 0000000..5a88538 --- /dev/null +++ b/template/sysroot/include/bits/gthr-default.h @@ -0,0 +1,298 @@ +/* Threads compatibility routines for libgcc2 and libobjc. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1997-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _GLIBCXX_GCC_GTHR_SINGLE_H +#define _GLIBCXX_GCC_GTHR_SINGLE_H + +/* Just provide compatibility for mutex handling. */ + +typedef int __gthread_key_t; +typedef int __gthread_once_t; +typedef int __gthread_mutex_t; +typedef int __gthread_recursive_mutex_t; + +#define __GTHREAD_ONCE_INIT 0 +#define __GTHREAD_MUTEX_INIT 0 +#define __GTHREAD_MUTEX_INIT_FUNCTION(mx) do {} while (0) +#define __GTHREAD_RECURSIVE_MUTEX_INIT 0 + +#define _GLIBCXX_UNUSED __attribute__((__unused__)) + +#ifdef _LIBOBJC + +/* Thread local storage for a single thread */ +static void *thread_local_storage = NULL; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +static inline int +__gthread_objc_init_thread_system (void) +{ + /* No thread support available */ + return -1; +} + +/* Close the threads subsystem. */ +static inline int +__gthread_objc_close_thread_system (void) +{ + /* No thread support available */ + return -1; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +static inline objc_thread_t +__gthread_objc_thread_detach (void (* func)(void *), void * arg _GLIBCXX_UNUSED) +{ + /* No thread support available */ + return NULL; +} + +/* Set the current thread's priority. */ +static inline int +__gthread_objc_thread_set_priority (int priority _GLIBCXX_UNUSED) +{ + /* No thread support available */ + return -1; +} + +/* Return the current thread's priority. */ +static inline int +__gthread_objc_thread_get_priority (void) +{ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +static inline void +__gthread_objc_thread_yield (void) +{ + return; +} + +/* Terminate the current thread. */ +static inline int +__gthread_objc_thread_exit (void) +{ + /* No thread support available */ + /* Should we really exit the program */ + /* exit (&__objc_thread_exit_status); */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +static inline objc_thread_t +__gthread_objc_thread_id (void) +{ + /* No thread support, use 1. */ + return (objc_thread_t) 1; +} + +/* Sets the thread's local storage pointer. */ +static inline int +__gthread_objc_thread_set_data (void *value) +{ + thread_local_storage = value; + return 0; +} + +/* Returns the thread's local storage pointer. */ +static inline void * +__gthread_objc_thread_get_data (void) +{ + return thread_local_storage; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +static inline int +__gthread_objc_mutex_allocate (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Deallocate a mutex. */ +static inline int +__gthread_objc_mutex_deallocate (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_lock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Try to grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_trylock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Unlock the mutex */ +static inline int +__gthread_objc_mutex_unlock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +static inline int +__gthread_objc_condition_allocate (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Deallocate a condition. */ +static inline int +__gthread_objc_condition_deallocate (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wait on the condition */ +static inline int +__gthread_objc_condition_wait (objc_condition_t condition _GLIBCXX_UNUSED, + objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wake up all threads waiting on this condition. */ +static inline int +__gthread_objc_condition_broadcast (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wake up one thread waiting on this condition. */ +static inline int +__gthread_objc_condition_signal (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +#else /* _LIBOBJC */ + +static inline int +__gthread_active_p (void) +{ + return 0; +} + +static inline int +__gthread_once (__gthread_once_t *__once _GLIBCXX_UNUSED, void (*__func) (void) _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int _GLIBCXX_UNUSED +__gthread_key_create (__gthread_key_t *__key _GLIBCXX_UNUSED, void (*__func) (void *) _GLIBCXX_UNUSED) +{ + return 0; +} + +static int _GLIBCXX_UNUSED +__gthread_key_delete (__gthread_key_t __key _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline void * +__gthread_getspecific (__gthread_key_t __key _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_setspecific (__gthread_key_t __key _GLIBCXX_UNUSED, const void *__v _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_destroy (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_lock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_trylock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_unlock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_lock (__mutex); +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_trylock (__mutex); +} + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_unlock (__mutex); +} + +static inline int +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_destroy (__mutex); +} + +#endif /* _LIBOBJC */ + +#undef _GLIBCXX_UNUSED + +#endif /* ! _GLIBCXX_GCC_GTHR_SINGLE_H */ diff --git a/template/sysroot/include/bits/gthr-posix.h b/template/sysroot/include/bits/gthr-posix.h new file mode 100644 index 0000000..336e614 --- /dev/null +++ b/template/sysroot/include/bits/gthr-posix.h @@ -0,0 +1,950 @@ +/* Threads compatibility routines for libgcc2 and libobjc. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1997-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _GLIBCXX_GCC_GTHR_POSIX_H +#define _GLIBCXX_GCC_GTHR_POSIX_H + +/* POSIX threads specific definitions. + Easy, since the interface is just one-to-one mapping. */ + +#define __GTHREADS 1 +#define __GTHREADS_CXX0X 1 + +#include + +#if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \ + || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK)) +# include +# if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0 +# define _GTHREAD_USE_MUTEX_TIMEDLOCK 1 +# else +# define _GTHREAD_USE_MUTEX_TIMEDLOCK 0 +# endif +#endif + +typedef pthread_t __gthread_t; +typedef pthread_key_t __gthread_key_t; +typedef pthread_once_t __gthread_once_t; +typedef pthread_mutex_t __gthread_mutex_t; +#ifndef __cplusplus +typedef pthread_rwlock_t __gthread_rwlock_t; +#endif +typedef pthread_mutex_t __gthread_recursive_mutex_t; +typedef pthread_cond_t __gthread_cond_t; +typedef struct timespec __gthread_time_t; + +/* POSIX like conditional variables are supported. Please look at comments + in gthr.h for details. */ +#define __GTHREAD_HAS_COND 1 + +#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function +#ifndef __cplusplus +#define __GTHREAD_RWLOCK_INIT PTHREAD_RWLOCK_INITIALIZER +#endif +#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) +#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#else +#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function +#endif +#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER +#define __GTHREAD_TIME_INIT {0,0} + +#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC +# undef __GTHREAD_MUTEX_INIT +#endif +#ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC +# undef __GTHREAD_RECURSIVE_MUTEX_INIT +# undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION +# define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function +#endif +#ifdef _GTHREAD_USE_COND_INIT_FUNC +# undef __GTHREAD_COND_INIT +# define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function +#endif + +#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK +# ifndef __gthrw_pragma +# define __gthrw_pragma(pragma) +# endif +# define __gthrw2(name,name2,type) \ + static __typeof(type) name \ + __attribute__ ((__weakref__(#name2), __copy__ (type))); \ + __gthrw_pragma(weak type) +# define __gthrw_(name) __gthrw_ ## name +#else +# define __gthrw2(name,name2,type) +# define __gthrw_(name) name +#endif + +/* Typically, __gthrw_foo is a weak reference to symbol foo. */ +#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name) + +__gthrw(pthread_once) +__gthrw(pthread_getspecific) +__gthrw(pthread_setspecific) + +__gthrw(pthread_create) +__gthrw(pthread_join) +__gthrw(pthread_equal) +__gthrw(pthread_self) +__gthrw(pthread_detach) +#ifndef __BIONIC__ +__gthrw(pthread_cancel) +#endif +__gthrw(sched_yield) + +__gthrw(pthread_mutex_lock) +__gthrw(pthread_mutex_trylock) +#if _GTHREAD_USE_MUTEX_TIMEDLOCK +__gthrw(pthread_mutex_timedlock) +#endif +__gthrw(pthread_mutex_unlock) +__gthrw(pthread_mutex_init) +__gthrw(pthread_mutex_destroy) + +__gthrw(pthread_cond_init) +__gthrw(pthread_cond_broadcast) +__gthrw(pthread_cond_signal) +__gthrw(pthread_cond_wait) +__gthrw(pthread_cond_timedwait) +__gthrw(pthread_cond_destroy) + +__gthrw(pthread_key_create) +__gthrw(pthread_key_delete) +__gthrw(pthread_mutexattr_init) +__gthrw(pthread_mutexattr_settype) +__gthrw(pthread_mutexattr_destroy) + +#ifndef __cplusplus +__gthrw(pthread_rwlock_rdlock) +__gthrw(pthread_rwlock_tryrdlock) +__gthrw(pthread_rwlock_wrlock) +__gthrw(pthread_rwlock_trywrlock) +__gthrw(pthread_rwlock_unlock) +#endif + +#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) +/* Objective-C. */ +__gthrw(pthread_exit) +#ifdef _POSIX_PRIORITY_SCHEDULING +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING +__gthrw(sched_get_priority_max) +__gthrw(sched_get_priority_min) +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +#endif /* _POSIX_PRIORITY_SCHEDULING */ +__gthrw(pthread_attr_destroy) +__gthrw(pthread_attr_init) +__gthrw(pthread_attr_setdetachstate) +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING +__gthrw(pthread_getschedparam) +__gthrw(pthread_setschedparam) +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +#endif /* _LIBOBJC || _LIBOBJC_WEAK */ + +#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK + +/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if + -pthreads is not specified. The functions are dummies and most return an + error value. However pthread_once returns 0 without invoking the routine + it is passed so we cannot pretend that the interface is active if -pthreads + is not specified. On Solaris 2.5.1, the interface is not exposed at all so + we need to play the usual game with weak symbols. On Solaris 10 and up, a + working interface is always exposed. On FreeBSD 6 and later, libc also + exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up + to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, + which means the alternate __gthread_active_p below cannot be used there. */ + +#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) + +static volatile int __gthread_active = -1; + +static void +__gthread_trigger (void) +{ + __gthread_active = 1; +} + +static inline int +__gthread_active_p (void) +{ + static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; + + /* Avoid reading __gthread_active twice on the main code path. */ + int __gthread_active_latest_value = __gthread_active; + + /* This test is not protected to avoid taking a lock on the main code + path so every update of __gthread_active in a threaded program must + be atomic with regard to the result of the test. */ + if (__builtin_expect (__gthread_active_latest_value < 0, 0)) + { + if (__gthrw_(pthread_once)) + { + /* If this really is a threaded program, then we must ensure that + __gthread_active has been set to 1 before exiting this block. */ + __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); + __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); + __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); + } + + /* Make sure we'll never enter this block again. */ + if (__gthread_active < 0) + __gthread_active = 0; + + __gthread_active_latest_value = __gthread_active; + } + + return __gthread_active_latest_value != 0; +} + +#else /* neither FreeBSD nor Solaris */ + +/* For a program to be multi-threaded the only thing that it certainly must + be using is pthread_create. However, there may be other libraries that + intercept pthread_create with their own definitions to wrap pthreads + functionality for some purpose. In those cases, pthread_create being + defined might not necessarily mean that libpthread is actually linked + in. + + For the GNU C library, we can use a known internal name. This is always + available in the ABI, but no other library would define it. That is + ideal, since any public pthread function might be intercepted just as + pthread_create might be. __pthread_key_create is an "internal" + implementation symbol, but it is part of the public exported ABI. Also, + it's among the symbols that the static libpthread.a always links in + whenever pthread_create is used, so there is no danger of a false + negative result in any statically-linked, multi-threaded program. + + For others, we choose pthread_cancel as a function that seems unlikely + to be redefined by an interceptor library. The bionic (Android) C + library does not provide pthread_cancel, so we do use pthread_create + there (and interceptor libraries lose). */ + +#ifdef __GLIBC__ +__gthrw2(__gthrw_(__pthread_key_create), + __pthread_key_create, + pthread_key_create) +# define GTHR_ACTIVE_PROXY __gthrw_(__pthread_key_create) +#elif defined (__BIONIC__) +# define GTHR_ACTIVE_PROXY __gthrw_(pthread_create) +#else +# define GTHR_ACTIVE_PROXY __gthrw_(pthread_cancel) +#endif + +static inline int +__gthread_active_p (void) +{ + static void *const __gthread_active_ptr + = __extension__ (void *) >HR_ACTIVE_PROXY; + return __gthread_active_ptr != 0; +} + +#endif /* FreeBSD or Solaris */ + +#else /* not __GXX_WEAK__ */ + +/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread + calls in shared flavors of the HP-UX C library. Most of the stubs + have no functionality. The details are described in the "libc cumulative + patch" for each subversion of HP-UX 11. There are two special interfaces + provided for checking whether an application is linked to a shared pthread + library or not. However, these interfaces aren't available in early + libpthread libraries. We also need a test that works for archive + libraries. We can't use pthread_once as some libc versions call the + init function. We also can't use pthread_create or pthread_attr_init + as these create a thread and thereby prevent changing the default stack + size. The function pthread_default_stacksize_np is available in both + the archive and shared versions of libpthread. It can be used to + determine the default pthread stack size. There is a stub in some + shared libc versions which returns a zero size if pthreads are not + active. We provide an equivalent stub to handle cases where libc + doesn't provide one. */ + +#if defined(__hppa__) && defined(__hpux__) + +static volatile int __gthread_active = -1; + +static inline int +__gthread_active_p (void) +{ + /* Avoid reading __gthread_active twice on the main code path. */ + int __gthread_active_latest_value = __gthread_active; + size_t __s; + + if (__builtin_expect (__gthread_active_latest_value < 0, 0)) + { + pthread_default_stacksize_np (0, &__s); + __gthread_active = __s ? 1 : 0; + __gthread_active_latest_value = __gthread_active; + } + + return __gthread_active_latest_value != 0; +} + +#else /* not hppa-hpux */ + +static inline int +__gthread_active_p (void) +{ + return 1; +} + +#endif /* hppa-hpux */ + +#endif /* __GXX_WEAK__ */ + +#ifdef _LIBOBJC + +/* This is the config.h file in libobjc/ */ +#include + +#ifdef HAVE_SCHED_H +# include +#endif + +/* Key structure for maintaining thread specific storage */ +static pthread_key_t _objc_thread_storage; +static pthread_attr_t _objc_thread_attribs; + +/* Thread local storage for a single thread */ +static void *thread_local_storage = NULL; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +static inline int +__gthread_objc_init_thread_system (void) +{ + if (__gthread_active_p ()) + { + /* Initialize the thread storage key. */ + if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) + { + /* The normal default detach state for threads is + * PTHREAD_CREATE_JOINABLE which causes threads to not die + * when you think they should. */ + if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 + && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, + PTHREAD_CREATE_DETACHED) == 0) + return 0; + } + } + + return -1; +} + +/* Close the threads subsystem. */ +static inline int +__gthread_objc_close_thread_system (void) +{ + if (__gthread_active_p () + && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 + && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) + return 0; + + return -1; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +static inline objc_thread_t +__gthread_objc_thread_detach (void (*func)(void *), void *arg) +{ + objc_thread_t thread_id; + pthread_t new_thread_handle; + + if (!__gthread_active_p ()) + return NULL; + + if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs, + (void *) func, arg))) + thread_id = (objc_thread_t) new_thread_handle; + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +static inline int +__gthread_objc_thread_set_priority (int priority) +{ + if (!__gthread_active_p ()) + return -1; + else + { +#ifdef _POSIX_PRIORITY_SCHEDULING +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + pthread_t thread_id = __gthrw_(pthread_self) (); + int policy; + struct sched_param params; + int priority_min, priority_max; + + if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) + { + if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) + return -1; + + if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) + return -1; + + if (priority > priority_max) + priority = priority_max; + else if (priority < priority_min) + priority = priority_min; + params.sched_priority = priority; + + /* + * The solaris 7 and several other man pages incorrectly state that + * this should be a pointer to policy but pthread.h is universally + * at odds with this. + */ + if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) + return 0; + } +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +#endif /* _POSIX_PRIORITY_SCHEDULING */ + return -1; + } +} + +/* Return the current thread's priority. */ +static inline int +__gthread_objc_thread_get_priority (void) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + if (__gthread_active_p ()) + { + int policy; + struct sched_param params; + + if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) + return params.sched_priority; + else + return -1; + } + else +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +#endif /* _POSIX_PRIORITY_SCHEDULING */ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +static inline void +__gthread_objc_thread_yield (void) +{ + if (__gthread_active_p ()) + __gthrw_(sched_yield) (); +} + +/* Terminate the current thread. */ +static inline int +__gthread_objc_thread_exit (void) +{ + if (__gthread_active_p ()) + /* exit the thread */ + __gthrw_(pthread_exit) (&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +static inline objc_thread_t +__gthread_objc_thread_id (void) +{ + if (__gthread_active_p ()) + return (objc_thread_t) __gthrw_(pthread_self) (); + else + return (objc_thread_t) 1; +} + +/* Sets the thread's local storage pointer. */ +static inline int +__gthread_objc_thread_set_data (void *value) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); + else + { + thread_local_storage = value; + return 0; + } +} + +/* Returns the thread's local storage pointer. */ +static inline void * +__gthread_objc_thread_get_data (void) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_getspecific) (_objc_thread_storage); + else + return thread_local_storage; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +static inline int +__gthread_objc_mutex_allocate (objc_mutex_t mutex) +{ + if (__gthread_active_p ()) + { + mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); + + if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) + { + objc_free (mutex->backend); + mutex->backend = NULL; + return -1; + } + } + + return 0; +} + +/* Deallocate a mutex. */ +static inline int +__gthread_objc_mutex_deallocate (objc_mutex_t mutex) +{ + if (__gthread_active_p ()) + { + int count; + + /* + * Posix Threads specifically require that the thread be unlocked + * for __gthrw_(pthread_mutex_destroy) to work. + */ + + do + { + count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); + if (count < 0) + return -1; + } + while (count); + + if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) + return -1; + + objc_free (mutex->backend); + mutex->backend = NULL; + } + return 0; +} + +/* Grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_lock (objc_mutex_t mutex) +{ + if (__gthread_active_p () + && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } + + return 0; +} + +/* Try to grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_trylock (objc_mutex_t mutex) +{ + if (__gthread_active_p () + && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } + + return 0; +} + +/* Unlock the mutex */ +static inline int +__gthread_objc_mutex_unlock (objc_mutex_t mutex) +{ + if (__gthread_active_p () + && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } + + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +static inline int +__gthread_objc_condition_allocate (objc_condition_t condition) +{ + if (__gthread_active_p ()) + { + condition->backend = objc_malloc (sizeof (pthread_cond_t)); + + if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) + { + objc_free (condition->backend); + condition->backend = NULL; + return -1; + } + } + + return 0; +} + +/* Deallocate a condition. */ +static inline int +__gthread_objc_condition_deallocate (objc_condition_t condition) +{ + if (__gthread_active_p ()) + { + if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) + return -1; + + objc_free (condition->backend); + condition->backend = NULL; + } + return 0; +} + +/* Wait on the condition */ +static inline int +__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, + (pthread_mutex_t *) mutex->backend); + else + return 0; +} + +/* Wake up all threads waiting on this condition. */ +static inline int +__gthread_objc_condition_broadcast (objc_condition_t condition) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); + else + return 0; +} + +/* Wake up one thread waiting on this condition. */ +static inline int +__gthread_objc_condition_signal (objc_condition_t condition) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); + else + return 0; +} + +#else /* _LIBOBJC */ + +static inline int +__gthread_create (__gthread_t *__threadid, void *(*__func) (void*), + void *__args) +{ + return __gthrw_(pthread_create) (__threadid, NULL, __func, __args); +} + +static inline int +__gthread_join (__gthread_t __threadid, void **__value_ptr) +{ + return __gthrw_(pthread_join) (__threadid, __value_ptr); +} + +static inline int +__gthread_detach (__gthread_t __threadid) +{ + return __gthrw_(pthread_detach) (__threadid); +} + +static inline int +__gthread_equal (__gthread_t __t1, __gthread_t __t2) +{ + return __gthrw_(pthread_equal) (__t1, __t2); +} + +static inline __gthread_t +__gthread_self (void) +{ + return __gthrw_(pthread_self) (); +} + +static inline int +__gthread_yield (void) +{ + return __gthrw_(sched_yield) (); +} + +static inline int +__gthread_once (__gthread_once_t *__once, void (*__func) (void)) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_once) (__once, __func); + else + return -1; +} + +static inline int +__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) +{ + return __gthrw_(pthread_key_create) (__key, __dtor); +} + +static inline int +__gthread_key_delete (__gthread_key_t __key) +{ + return __gthrw_(pthread_key_delete) (__key); +} + +static inline void * +__gthread_getspecific (__gthread_key_t __key) +{ + return __gthrw_(pthread_getspecific) (__key); +} + +static inline int +__gthread_setspecific (__gthread_key_t __key, const void *__ptr) +{ + return __gthrw_(pthread_setspecific) (__key, __ptr); +} + +static inline void +__gthread_mutex_init_function (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + __gthrw_(pthread_mutex_init) (__mutex, NULL); +} + +static inline int +__gthread_mutex_destroy (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_mutex_destroy) (__mutex); + else + return 0; +} + +static inline int +__gthread_mutex_lock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_mutex_lock) (__mutex); + else + return 0; +} + +static inline int +__gthread_mutex_trylock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_mutex_trylock) (__mutex); + else + return 0; +} + +#if _GTHREAD_USE_MUTEX_TIMEDLOCK +static inline int +__gthread_mutex_timedlock (__gthread_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout); + else + return 0; +} +#endif + +static inline int +__gthread_mutex_unlock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_mutex_unlock) (__mutex); + else + return 0; +} + +#if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \ + || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC) +static inline int +__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + { + pthread_mutexattr_t __attr; + int __r; + + __r = __gthrw_(pthread_mutexattr_init) (&__attr); + if (!__r) + __r = __gthrw_(pthread_mutexattr_settype) (&__attr, + PTHREAD_MUTEX_RECURSIVE); + if (!__r) + __r = __gthrw_(pthread_mutex_init) (__mutex, &__attr); + if (!__r) + __r = __gthrw_(pthread_mutexattr_destroy) (&__attr); + return __r; + } + return 0; +} +#endif + +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_lock (__mutex); +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_trylock (__mutex); +} + +#if _GTHREAD_USE_MUTEX_TIMEDLOCK +static inline int +__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + return __gthread_mutex_timedlock (__mutex, __abs_timeout); +} +#endif + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_unlock (__mutex); +} + +static inline int +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_destroy (__mutex); +} + +#ifdef _GTHREAD_USE_COND_INIT_FUNC +static inline void +__gthread_cond_init_function (__gthread_cond_t *__cond) +{ + if (__gthread_active_p ()) + __gthrw_(pthread_cond_init) (__cond, NULL); +} +#endif + +static inline int +__gthread_cond_broadcast (__gthread_cond_t *__cond) +{ + return __gthrw_(pthread_cond_broadcast) (__cond); +} + +static inline int +__gthread_cond_signal (__gthread_cond_t *__cond) +{ + return __gthrw_(pthread_cond_signal) (__cond); +} + +static inline int +__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) +{ + return __gthrw_(pthread_cond_wait) (__cond, __mutex); +} + +static inline int +__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout); +} + +static inline int +__gthread_cond_wait_recursive (__gthread_cond_t *__cond, + __gthread_recursive_mutex_t *__mutex) +{ + return __gthread_cond_wait (__cond, __mutex); +} + +static inline int +__gthread_cond_destroy (__gthread_cond_t* __cond) +{ + return __gthrw_(pthread_cond_destroy) (__cond); +} + +#ifndef __cplusplus +static inline int +__gthread_rwlock_rdlock (__gthread_rwlock_t *__rwlock) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_rdlock) (__rwlock); + else + return 0; +} + +static inline int +__gthread_rwlock_tryrdlock (__gthread_rwlock_t *__rwlock) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_tryrdlock) (__rwlock); + else + return 0; +} + +static inline int +__gthread_rwlock_wrlock (__gthread_rwlock_t *__rwlock) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_wrlock) (__rwlock); + else + return 0; +} + +static inline int +__gthread_rwlock_trywrlock (__gthread_rwlock_t *__rwlock) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_trywrlock) (__rwlock); + else + return 0; +} + +static inline int +__gthread_rwlock_unlock (__gthread_rwlock_t *__rwlock) +{ + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_unlock) (__rwlock); + else + return 0; +} +#endif + +#endif /* _LIBOBJC */ + +#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */ diff --git a/template/sysroot/include/bits/gthr-single.h b/template/sysroot/include/bits/gthr-single.h new file mode 100644 index 0000000..5a88538 --- /dev/null +++ b/template/sysroot/include/bits/gthr-single.h @@ -0,0 +1,298 @@ +/* Threads compatibility routines for libgcc2 and libobjc. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1997-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _GLIBCXX_GCC_GTHR_SINGLE_H +#define _GLIBCXX_GCC_GTHR_SINGLE_H + +/* Just provide compatibility for mutex handling. */ + +typedef int __gthread_key_t; +typedef int __gthread_once_t; +typedef int __gthread_mutex_t; +typedef int __gthread_recursive_mutex_t; + +#define __GTHREAD_ONCE_INIT 0 +#define __GTHREAD_MUTEX_INIT 0 +#define __GTHREAD_MUTEX_INIT_FUNCTION(mx) do {} while (0) +#define __GTHREAD_RECURSIVE_MUTEX_INIT 0 + +#define _GLIBCXX_UNUSED __attribute__((__unused__)) + +#ifdef _LIBOBJC + +/* Thread local storage for a single thread */ +static void *thread_local_storage = NULL; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +static inline int +__gthread_objc_init_thread_system (void) +{ + /* No thread support available */ + return -1; +} + +/* Close the threads subsystem. */ +static inline int +__gthread_objc_close_thread_system (void) +{ + /* No thread support available */ + return -1; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +static inline objc_thread_t +__gthread_objc_thread_detach (void (* func)(void *), void * arg _GLIBCXX_UNUSED) +{ + /* No thread support available */ + return NULL; +} + +/* Set the current thread's priority. */ +static inline int +__gthread_objc_thread_set_priority (int priority _GLIBCXX_UNUSED) +{ + /* No thread support available */ + return -1; +} + +/* Return the current thread's priority. */ +static inline int +__gthread_objc_thread_get_priority (void) +{ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +static inline void +__gthread_objc_thread_yield (void) +{ + return; +} + +/* Terminate the current thread. */ +static inline int +__gthread_objc_thread_exit (void) +{ + /* No thread support available */ + /* Should we really exit the program */ + /* exit (&__objc_thread_exit_status); */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +static inline objc_thread_t +__gthread_objc_thread_id (void) +{ + /* No thread support, use 1. */ + return (objc_thread_t) 1; +} + +/* Sets the thread's local storage pointer. */ +static inline int +__gthread_objc_thread_set_data (void *value) +{ + thread_local_storage = value; + return 0; +} + +/* Returns the thread's local storage pointer. */ +static inline void * +__gthread_objc_thread_get_data (void) +{ + return thread_local_storage; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +static inline int +__gthread_objc_mutex_allocate (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Deallocate a mutex. */ +static inline int +__gthread_objc_mutex_deallocate (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_lock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Try to grab a lock on a mutex. */ +static inline int +__gthread_objc_mutex_trylock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Unlock the mutex */ +static inline int +__gthread_objc_mutex_unlock (objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +static inline int +__gthread_objc_condition_allocate (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Deallocate a condition. */ +static inline int +__gthread_objc_condition_deallocate (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wait on the condition */ +static inline int +__gthread_objc_condition_wait (objc_condition_t condition _GLIBCXX_UNUSED, + objc_mutex_t mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wake up all threads waiting on this condition. */ +static inline int +__gthread_objc_condition_broadcast (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +/* Wake up one thread waiting on this condition. */ +static inline int +__gthread_objc_condition_signal (objc_condition_t condition _GLIBCXX_UNUSED) +{ + return 0; +} + +#else /* _LIBOBJC */ + +static inline int +__gthread_active_p (void) +{ + return 0; +} + +static inline int +__gthread_once (__gthread_once_t *__once _GLIBCXX_UNUSED, void (*__func) (void) _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int _GLIBCXX_UNUSED +__gthread_key_create (__gthread_key_t *__key _GLIBCXX_UNUSED, void (*__func) (void *) _GLIBCXX_UNUSED) +{ + return 0; +} + +static int _GLIBCXX_UNUSED +__gthread_key_delete (__gthread_key_t __key _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline void * +__gthread_getspecific (__gthread_key_t __key _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_setspecific (__gthread_key_t __key _GLIBCXX_UNUSED, const void *__v _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_destroy (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_lock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_trylock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_mutex_unlock (__gthread_mutex_t *__mutex _GLIBCXX_UNUSED) +{ + return 0; +} + +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_lock (__mutex); +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_trylock (__mutex); +} + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_unlock (__mutex); +} + +static inline int +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) +{ + return __gthread_mutex_destroy (__mutex); +} + +#endif /* _LIBOBJC */ + +#undef _GLIBCXX_UNUSED + +#endif /* ! _GLIBCXX_GCC_GTHR_SINGLE_H */ diff --git a/template/sysroot/include/bits/gthr.h b/template/sysroot/include/bits/gthr.h new file mode 100644 index 0000000..9da4264 --- /dev/null +++ b/template/sysroot/include/bits/gthr.h @@ -0,0 +1,163 @@ +/* Threads compatibility routines for libgcc2. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1997-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _GLIBCXX_GCC_GTHR_H +#define _GLIBCXX_GCC_GTHR_H + +#ifndef _GLIBCXX_HIDE_EXPORTS +#pragma GCC visibility push(default) +#endif + +/* If this file is compiled with threads support, it must + #define __GTHREADS 1 + to indicate that threads support is present. Also it has define + function + int __gthread_active_p () + that returns 1 if thread system is active, 0 if not. + + The threads interface must define the following types: + __gthread_key_t + __gthread_once_t + __gthread_mutex_t + __gthread_recursive_mutex_t + + The threads interface must define the following macros: + + __GTHREAD_ONCE_INIT + to initialize __gthread_once_t + __GTHREAD_MUTEX_INIT + to initialize __gthread_mutex_t to get a fast + non-recursive mutex. + __GTHREAD_MUTEX_INIT_FUNCTION + to initialize __gthread_mutex_t to get a fast + non-recursive mutex. + Define this to a function which looks like this: + void __GTHREAD_MUTEX_INIT_FUNCTION (__gthread_mutex_t *) + Some systems can't initialize a mutex without a + function call. Don't define __GTHREAD_MUTEX_INIT in this case. + __GTHREAD_RECURSIVE_MUTEX_INIT + __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION + as above, but for a recursive mutex. + + The threads interface must define the following static functions: + + int __gthread_once (__gthread_once_t *once, void (*func) ()) + + int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *)) + int __gthread_key_delete (__gthread_key_t key) + + void *__gthread_getspecific (__gthread_key_t key) + int __gthread_setspecific (__gthread_key_t key, const void *ptr) + + int __gthread_mutex_destroy (__gthread_mutex_t *mutex); + int __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex); + + int __gthread_mutex_lock (__gthread_mutex_t *mutex); + int __gthread_mutex_trylock (__gthread_mutex_t *mutex); + int __gthread_mutex_unlock (__gthread_mutex_t *mutex); + + int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex); + int __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex); + int __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex); + + The following are supported in POSIX threads only. They are required to + fix a deadlock in static initialization inside libsupc++. The header file + gthr-posix.h defines a symbol __GTHREAD_HAS_COND to signify that these extra + features are supported. + + Types: + __gthread_cond_t + + Macros: + __GTHREAD_COND_INIT + __GTHREAD_COND_INIT_FUNCTION + + Interface: + int __gthread_cond_broadcast (__gthread_cond_t *cond); + int __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex); + int __gthread_cond_wait_recursive (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex); + + All functions returning int should return zero on success or the error + number. If the operation is not supported, -1 is returned. + + If the following are also defined, you should + #define __GTHREADS_CXX0X 1 + to enable the c++0x thread library. + + Types: + __gthread_t + __gthread_time_t + + Interface: + int __gthread_create (__gthread_t *thread, void *(*func) (void*), + void *args); + int __gthread_join (__gthread_t thread, void **value_ptr); + int __gthread_detach (__gthread_t thread); + int __gthread_equal (__gthread_t t1, __gthread_t t2); + __gthread_t __gthread_self (void); + int __gthread_yield (void); + + int __gthread_mutex_timedlock (__gthread_mutex_t *m, + const __gthread_time_t *abs_timeout); + int __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *m, + const __gthread_time_t *abs_time); + + int __gthread_cond_signal (__gthread_cond_t *cond); + int __gthread_cond_timedwait (__gthread_cond_t *cond, + __gthread_mutex_t *mutex, + const __gthread_time_t *abs_timeout); + +*/ + +#if __GXX_WEAK__ +/* The pe-coff weak support isn't fully compatible to ELF's weak. + For static libraries it might would work, but as we need to deal + with shared versions too, we disable it for mingw-targets. */ +#ifdef __MINGW32__ +#undef _GLIBCXX_GTHREAD_USE_WEAK +#define _GLIBCXX_GTHREAD_USE_WEAK 0 +#endif + +#ifdef _GLIBCXX___GLIBC_PREREQ +#if _GLIBCXX___GLIBC_PREREQ(2, 34) && !defined(_GLIBCXX___gnu_GLIBCXX__hurd_GLIBCXX___) +/* glibc 2.34 and later has all pthread_* APIs inside of libc, + no need to link separately with -lpthread. */ +#undef _GLIBCXX_GTHREAD_USE_WEAK +#define _GLIBCXX_GTHREAD_USE_WEAK 0 +#endif +#endif + +#ifndef _GLIBCXX_GTHREAD_USE_WEAK +#define _GLIBCXX_GTHREAD_USE_WEAK 1 +#endif +#endif +#include + +#ifndef _GLIBCXX_HIDE_EXPORTS +#pragma GCC visibility pop +#endif + +#endif /* ! _GLIBCXX_GCC_GTHR_H */ diff --git a/template/sysroot/include/bits/hash_bytes.h b/template/sysroot/include/bits/hash_bytes.h new file mode 100644 index 0000000..f3f965c --- /dev/null +++ b/template/sysroot/include/bits/hash_bytes.h @@ -0,0 +1,59 @@ +// Declarations for hash functions. -*- C++ -*- + +// Copyright (C) 2010-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hash_bytes.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _HASH_BYTES_H +#define _HASH_BYTES_H 1 + +#pragma GCC system_header + +#include + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Hash function implementation for the nontrivial specialization. + // All of them are based on a primitive that hashes a pointer to a + // byte array. The actual hash algorithm is not guaranteed to stay + // the same from release to release -- it may be updated or tuned to + // improve hash quality or speed. + size_t + _Hash_bytes(const void* __ptr, size_t __len, size_t __seed); + + // A similar hash primitive, using the FNV hash algorithm. This + // algorithm is guaranteed to stay the same from release to release. + // (although it might not produce the same values on different + // machines.) + size_t + _Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/invoke.h b/template/sysroot/include/bits/invoke.h new file mode 100644 index 0000000..2c66a36 --- /dev/null +++ b/template/sysroot/include/bits/invoke.h @@ -0,0 +1,160 @@ +// Implementation of INVOKE -*- C++ -*- + +// Copyright (C) 2016-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/invoke.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_INVOKE_H +#define _GLIBCXX_INVOKE_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include // forward + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // Used by __invoke_impl instead of std::forward<_Tp> so that a + // reference_wrapper is converted to an lvalue-reference. + template::type> + constexpr _Up&& + __invfwd(typename remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Up&&>(__t); } + + template + constexpr _Res + __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) + { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { + return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); + } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) + { return __invfwd<_Tp>(__t).*__f; } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) + { return (*std::forward<_Tp>(__t)).*__f; } + + /// Invoke a callable object. + template + constexpr typename __invoke_result<_Callable, _Args...>::type + __invoke(_Callable&& __fn, _Args&&... __args) + noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + +#if __cplusplus >= 201703L + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr enable_if_t, _Res> + __invoke_r(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + if constexpr (is_void_v<_Res>) + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + else + return std::__invoke_impl<__type>(__tag{}, + std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#else // C++11 or C++14 + // This is a non-SFINAE-friendly std::invoke_r(fn, args...) for C++11/14. + // It's used in std::function, std::bind, and std::packaged_task. Only + // std::function is constrained on is_invocable_r, but that is checked on + // construction so doesn't need to be checked again when calling __invoke_r. + // Consequently, these __invoke_r overloads do not check for invocable + // arguments, nor check that the invoke result is convertible to R. + + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr __enable_if_t::value, _Res> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; +#if __has_builtin(__reference_converts_from_temporary) + static_assert(!__reference_converts_from_temporary(_Res, __type), + "INVOKE must not create a dangling reference"); +#endif + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + + // INVOKE when R is cv void + template + _GLIBCXX14_CONSTEXPR __enable_if_t::value, _Res> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // C++11 or C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_INVOKE_H diff --git a/template/sysroot/include/bits/iterator_concepts.h b/template/sysroot/include/bits/iterator_concepts.h new file mode 100644 index 0000000..ce0b8a1 --- /dev/null +++ b/template/sysroot/include/bits/iterator_concepts.h @@ -0,0 +1,1021 @@ +// Concepts and traits for use with iterators -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/iterator_concepts.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _ITERATOR_CONCEPTS_H +#define _ITERATOR_CONCEPTS_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 202002L +#include +#include // to_address +#include // identity, ranges::less + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** A sentinel type that can be used to check for the end of a range. + * + * For some iterator types the past-the-end sentinel value is independent + * of the underlying sequence, and a default sentinel can be used with them. + * For example, a `std::counted_iterator` keeps a count of how many elements + * remain, and so checking for the past-the-end value only requires checking + * if that count has reached zero. A past-the-end `std::istream_iterator` is + * equal to the default-constructed value, which can be easily checked. + * + * Comparing iterators of these types to `std::default_sentinel` is a + * convenient way to check if the end has been reached. + * + * @since C++20 + */ + struct default_sentinel_t { }; + + /// A default sentinel value. + inline constexpr default_sentinel_t default_sentinel{}; + +#if __cpp_lib_concepts + struct input_iterator_tag; + struct output_iterator_tag; + struct forward_iterator_tag; + struct bidirectional_iterator_tag; + struct random_access_iterator_tag; + struct contiguous_iterator_tag; + + template + struct iterator_traits; + + template requires is_object_v<_Tp> + struct iterator_traits<_Tp*>; + + template + struct __iterator_traits; + + namespace __detail + { + template + using __with_ref = _Tp&; + + template + concept __can_reference = requires { typename __with_ref<_Tp>; }; + + template + concept __dereferenceable = requires(_Tp& __t) + { + { *__t } -> __can_reference; + }; + } // namespace __detail + + template<__detail::__dereferenceable _Tp> + using iter_reference_t = decltype(*std::declval<_Tp&>()); + + namespace ranges + { + /// @cond undocumented + namespace __imove + { + void iter_move() = delete; + + template + concept __adl_imove + = (std::__detail::__class_or_enum>) + && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); }; + + struct _IterMove + { + private: + template + struct __result + { using type = iter_reference_t<_Tp>; }; + + template + requires __adl_imove<_Tp> + struct __result<_Tp> + { using type = decltype(iter_move(std::declval<_Tp>())); }; + + template + requires (!__adl_imove<_Tp>) + && is_lvalue_reference_v> + struct __result<_Tp> + { using type = remove_reference_t>&&; }; + + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_imove<_Tp>) + return noexcept(iter_move(std::declval<_Tp>())); + else + return noexcept(*std::declval<_Tp>()); + } + + public: + // The result type of iter_move(std::declval<_Tp>()) + template + using __type = typename __result<_Tp>::type; + + template + [[nodiscard]] + constexpr __type<_Tp> + operator()(_Tp&& __e) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__adl_imove<_Tp>) + return iter_move(static_cast<_Tp&&>(__e)); + else if constexpr (is_lvalue_reference_v>) + return static_cast<__type<_Tp>>(*__e); + else + return *__e; + } + }; + } // namespace __imove + /// @endcond + + inline namespace _Cpo { + inline constexpr __imove::_IterMove iter_move{}; + } + } // namespace ranges + + template<__detail::__dereferenceable _Tp> + requires __detail::__can_reference> + using iter_rvalue_reference_t = ranges::__imove::_IterMove::__type<_Tp&>; + + template struct incrementable_traits { }; + + template requires is_object_v<_Tp> + struct incrementable_traits<_Tp*> + { using difference_type = ptrdiff_t; }; + + template + struct incrementable_traits + : incrementable_traits<_Iter> { }; + + template requires requires { typename _Tp::difference_type; } + struct incrementable_traits<_Tp> + { using difference_type = typename _Tp::difference_type; }; + + template + requires (!requires { typename _Tp::difference_type; } + && requires(const _Tp& __a, const _Tp& __b) + { { __a - __b } -> integral; }) + struct incrementable_traits<_Tp> + { + using difference_type + = make_signed_t() - std::declval<_Tp>())>; + }; + +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // __int128 is incrementable even if !integral<__int128> + template<> + struct incrementable_traits<__int128> + { using difference_type = __int128; }; + + template<> + struct incrementable_traits + { using difference_type = __int128; }; +#endif + + namespace __detail + { + // An iterator such that iterator_traits<_Iter> names a specialization + // generated from the primary template. + template + concept __primary_traits_iter + = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>); + + template + struct __iter_traits_impl + { using type = iterator_traits<_Iter>; }; + + template + requires __primary_traits_iter<_Iter> + struct __iter_traits_impl<_Iter, _Tp> + { using type = _Tp; }; + + // ITER_TRAITS + template + using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; + + template + using __iter_diff_t = typename + __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; + } // namespace __detail + + template + using iter_difference_t = __detail::__iter_diff_t>; + + namespace __detail + { + template struct __cond_value_type { }; + + template requires is_object_v<_Tp> + struct __cond_value_type<_Tp> + { using value_type = remove_cv_t<_Tp>; }; + + template + concept __has_member_value_type + = requires { typename _Tp::value_type; }; + + template + concept __has_member_element_type + = requires { typename _Tp::element_type; }; + + } // namespace __detail + + template struct indirectly_readable_traits { }; + + template + struct indirectly_readable_traits<_Tp*> + : __detail::__cond_value_type<_Tp> + { }; + + template requires is_array_v<_Iter> + struct indirectly_readable_traits<_Iter> + { using value_type = remove_cv_t>; }; + + template + struct indirectly_readable_traits + : indirectly_readable_traits<_Iter> + { }; + + template<__detail::__has_member_value_type _Tp> + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + template<__detail::__has_member_element_type _Tp> + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3446. indirectly_readable_traits ambiguity for types with both [...] + template<__detail::__has_member_value_type _Tp> + requires __detail::__has_member_element_type<_Tp> + && same_as, + remove_cv_t> + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3541. indirectly_readable_traits should be SFINAE-friendly for all types + template<__detail::__has_member_value_type _Tp> + requires __detail::__has_member_element_type<_Tp> + struct indirectly_readable_traits<_Tp> + { }; + + namespace __detail + { + template + using __iter_value_t = typename + __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type; + } // namespace __detail + + template + using iter_value_t = __detail::__iter_value_t>; + + namespace __detail + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3420. cpp17-iterator should check [type] looks like an iterator first + template + concept __cpp17_iterator = requires(_Iter __it) + { + { *__it } -> __can_reference; + { ++__it } -> same_as<_Iter&>; + { *__it++ } -> __can_reference; + } && copyable<_Iter>; + + template + concept __cpp17_input_iterator = __cpp17_iterator<_Iter> + && equality_comparable<_Iter> + && requires(_Iter __it) + { + typename incrementable_traits<_Iter>::difference_type; + typename indirectly_readable_traits<_Iter>::value_type; + typename common_reference_t&&, + typename indirectly_readable_traits<_Iter>::value_type&>; + typename common_reference_t::value_type&>; + requires signed_integral< + typename incrementable_traits<_Iter>::difference_type>; + }; + + template + concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter> + && constructible_from<_Iter> + && is_lvalue_reference_v> + && same_as>, + typename indirectly_readable_traits<_Iter>::value_type> + && requires(_Iter __it) + { + { __it++ } -> convertible_to; + { *__it++ } -> same_as>; + }; + + template + concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter> + && requires(_Iter __it) + { + { --__it } -> same_as<_Iter&>; + { __it-- } -> convertible_to; + { *__it-- } -> same_as>; + }; + + template + concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter> + && totally_ordered<_Iter> + && requires(_Iter __it, + typename incrementable_traits<_Iter>::difference_type __n) + { + { __it += __n } -> same_as<_Iter&>; + { __it -= __n } -> same_as<_Iter&>; + { __it + __n } -> same_as<_Iter>; + { __n + __it } -> same_as<_Iter>; + { __it - __n } -> same_as<_Iter>; + { __it - __it } -> same_as; + { __it[__n] } -> convertible_to>; + }; + + template + concept __iter_with_nested_types = requires { + typename _Iter::iterator_category; + typename _Iter::value_type; + typename _Iter::difference_type; + typename _Iter::reference; + }; + + template + concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; + + template + concept __iter_without_category + = !requires { typename _Iter::iterator_category; }; + + } // namespace __detail + + template + requires __detail::__iter_with_nested_types<_Iterator> + struct __iterator_traits<_Iterator, void> + { + private: + template + struct __ptr + { using type = void; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter> + { using type = typename _Iter::pointer; }; + + public: + using iterator_category = typename _Iterator::iterator_category; + using value_type = typename _Iterator::value_type; + using difference_type = typename _Iterator::difference_type; + using pointer = typename __ptr<_Iterator>::type; + using reference = typename _Iterator::reference; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_input_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + private: + template + struct __cat + { using type = input_iterator_tag; }; + + template + requires requires { typename _Iter::iterator_category; } + struct __cat<_Iter> + { using type = typename _Iter::iterator_category; }; + + template + requires __detail::__iter_without_category<_Iter> + && __detail::__cpp17_randacc_iterator<_Iter> + struct __cat<_Iter> + { using type = random_access_iterator_tag; }; + + template + requires __detail::__iter_without_category<_Iter> + && __detail::__cpp17_bidi_iterator<_Iter> + struct __cat<_Iter> + { using type = bidirectional_iterator_tag; }; + + template + requires __detail::__iter_without_category<_Iter> + && __detail::__cpp17_fwd_iterator<_Iter> + struct __cat<_Iter> + { using type = forward_iterator_tag; }; + + template + struct __ptr + { using type = void; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter> + { using type = typename _Iter::pointer; }; + + template + requires (!requires { typename _Iter::pointer; } + && requires(_Iter& __it) { __it.operator->(); }) + struct __ptr<_Iter> + { using type = decltype(std::declval<_Iter&>().operator->()); }; + + template + struct __ref + { using type = iter_reference_t<_Iter>; }; + + template requires requires { typename _Iter::reference; } + struct __ref<_Iter> + { using type = typename _Iter::reference; }; + + public: + using iterator_category = typename __cat<_Iterator>::type; + using value_type + = typename indirectly_readable_traits<_Iterator>::value_type; + using difference_type + = typename incrementable_traits<_Iterator>::difference_type; + using pointer = typename __ptr<_Iterator>::type; + using reference = typename __ref<_Iterator>::type; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + private: + template + struct __diff + { using type = void; }; + + template + requires requires + { typename incrementable_traits<_Iter>::difference_type; } + struct __diff<_Iter> + { + using type = typename incrementable_traits<_Iter>::difference_type; + }; + + public: + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __diff<_Iterator>::type; + using pointer = void; + using reference = void; + }; + + namespace __detail + { + template + struct __iter_concept_impl; + + // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid. + template + requires requires { typename __iter_traits<_Iter>::iterator_concept; } + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_concept; }; + + // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && requires { typename __iter_traits<_Iter>::iterator_category; }) + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_category; }; + + // Otherwise, random_access_tag if iterator_traits is not specialized. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && !requires { typename __iter_traits<_Iter>::iterator_category; } + && __primary_traits_iter<_Iter>) + struct __iter_concept_impl<_Iter> + { using type = random_access_iterator_tag; }; + + // Otherwise, there is no ITER_CONCEPT(I) type. + template + struct __iter_concept_impl + { }; + + // ITER_CONCEPT + template + using __iter_concept = typename __iter_concept_impl<_Iter>::type; + + template + concept __indirectly_readable_impl = requires + { + typename iter_value_t<_In>; + typename iter_reference_t<_In>; + typename iter_rvalue_reference_t<_In>; + requires same_as, + iter_reference_t<_In>>; + requires same_as, + iter_rvalue_reference_t<_In>>; + } + && common_reference_with&&, iter_value_t<_In>&> + && common_reference_with&&, + iter_rvalue_reference_t<_In>&&> + && common_reference_with&&, + const iter_value_t<_In>&>; + + } // namespace __detail + + /// Requirements for types that are readable by applying operator*. + template + concept indirectly_readable + = __detail::__indirectly_readable_impl>; + + template + using iter_common_reference_t + = common_reference_t, iter_value_t<_Tp>&>; + + /// Requirements for writing a value into an iterator's referenced object. + template + concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) + { + *__o = std::forward<_Tp>(__t); + *std::forward<_Out>(__o) = std::forward<_Tp>(__t); + const_cast&&>(*__o) + = std::forward<_Tp>(__t); + const_cast&&>(*std::forward<_Out>(__o)) + = std::forward<_Tp>(__t); + }; + + namespace ranges::__detail + { + class __max_diff_type; + class __max_size_type; + + __extension__ + template + concept __is_signed_int128 +#if __SIZEOF_INT128__ + = same_as<_Tp, __int128>; +#else + = false; +#endif + + __extension__ + template + concept __is_unsigned_int128 +#if __SIZEOF_INT128__ + = same_as<_Tp, unsigned __int128>; +#else + = false; +#endif + + template + concept __cv_bool = same_as; + + template + concept __integral_nonbool = integral<_Tp> && !__cv_bool<_Tp>; + + template + concept __is_int128 = __is_signed_int128<_Tp> || __is_unsigned_int128<_Tp>; + + template + concept __is_integer_like = __integral_nonbool<_Tp> + || __is_int128<_Tp> + || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>; + + template + concept __is_signed_integer_like = signed_integral<_Tp> + || __is_signed_int128<_Tp> + || same_as<_Tp, __max_diff_type>; + + } // namespace ranges::__detail + + namespace __detail { using ranges::__detail::__is_signed_integer_like; } + + /// Requirements on types that can be incremented with ++. + template + concept weakly_incrementable = movable<_Iter> + && requires(_Iter __i) + { + typename iter_difference_t<_Iter>; + requires __detail::__is_signed_integer_like>; + { ++__i } -> same_as<_Iter&>; + __i++; + }; + + template + concept incrementable = regular<_Iter> && weakly_incrementable<_Iter> + && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; }; + + template + concept input_or_output_iterator + = requires(_Iter __i) { { *__i } -> __detail::__can_reference; } + && weakly_incrementable<_Iter>; + + template + concept sentinel_for = semiregular<_Sent> + && input_or_output_iterator<_Iter> + && __detail::__weakly_eq_cmp_with<_Sent, _Iter>; + + template + inline constexpr bool disable_sized_sentinel_for = false; + + template + concept sized_sentinel_for = sentinel_for<_Sent, _Iter> + && !disable_sized_sentinel_for, remove_cv_t<_Iter>> + && requires(const _Iter& __i, const _Sent& __s) + { + { __s - __i } -> same_as>; + { __i - __s } -> same_as>; + }; + + template + concept input_iterator = input_or_output_iterator<_Iter> + && indirectly_readable<_Iter> + && requires { typename __detail::__iter_concept<_Iter>; } + && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; + + template + concept output_iterator = input_or_output_iterator<_Iter> + && indirectly_writable<_Iter, _Tp> + && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); }; + + template + concept forward_iterator = input_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag> + && incrementable<_Iter> && sentinel_for<_Iter, _Iter>; + + template + concept bidirectional_iterator = forward_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + bidirectional_iterator_tag> + && requires(_Iter __i) + { + { --__i } -> same_as<_Iter&>; + { __i-- } -> same_as<_Iter>; + }; + + template + concept random_access_iterator = bidirectional_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + random_access_iterator_tag> + && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter> + && requires(_Iter __i, const _Iter __j, + const iter_difference_t<_Iter> __n) + { + { __i += __n } -> same_as<_Iter&>; + { __j + __n } -> same_as<_Iter>; + { __n + __j } -> same_as<_Iter>; + { __i -= __n } -> same_as<_Iter&>; + { __j - __n } -> same_as<_Iter>; + { __j[__n] } -> same_as>; + }; + + template + concept contiguous_iterator = random_access_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag> + && is_lvalue_reference_v> + && same_as, remove_cvref_t>> + && requires(const _Iter& __i) + { + { std::to_address(__i) } + -> same_as>>; + }; + + // [indirectcallable], indirect callable requirements + + // [indirectcallable.indirectinvocable], indirect callables + + template + concept indirectly_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> + && invocable<_Fn&, iter_reference_t<_Iter>> + && invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirectly_regular_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> + && regular_invocable<_Fn&, iter_value_t<_Iter>&> + && regular_invocable<_Fn&, iter_reference_t<_Iter>> + && regular_invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirect_unary_predicate = indirectly_readable<_Iter> + && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> + && predicate<_Fn&, iter_reference_t<_Iter>> + && predicate<_Fn&, iter_common_reference_t<_Iter>>; + + template + concept indirect_binary_predicate + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && predicate<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_equivalence_relation + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, + iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_strict_weak_order + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + requires (indirectly_readable<_Is> && ...) + && invocable<_Fn, iter_reference_t<_Is>...> + using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; + + namespace __detail + { + template + struct __projected + { + struct __type + { + using value_type = remove_cvref_t>; + indirect_result_t<_Proj&, _Iter> operator*() const; // not defined + }; + }; + + template + struct __projected<_Iter, _Proj> + { + struct __type + { + using value_type = remove_cvref_t>; + using difference_type = iter_difference_t<_Iter>; + indirect_result_t<_Proj&, _Iter> operator*() const; // not defined + }; + }; + } // namespace __detail + + /// [projected], projected + template _Proj> + using projected = typename __detail::__projected<_Iter, _Proj>::__type; + + // [alg.req], common algorithm requirements + + /// [alg.req.ind.move], concept `indirectly_movable` + + template + concept indirectly_movable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; + + template + concept indirectly_movable_storable = indirectly_movable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>> + && movable> + && constructible_from, iter_rvalue_reference_t<_In>> + && assignable_from&, iter_rvalue_reference_t<_In>>; + + /// [alg.req.ind.copy], concept `indirectly_copyable` + template + concept indirectly_copyable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_reference_t<_In>>; + + template + concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>&> + && indirectly_writable<_Out, const iter_value_t<_In>&> + && indirectly_writable<_Out, iter_value_t<_In>&&> + && indirectly_writable<_Out, const iter_value_t<_In>&&> + && copyable> + && constructible_from, iter_reference_t<_In>> + && assignable_from&, iter_reference_t<_In>>; + +namespace ranges +{ + /// @cond undocumented + namespace __iswap + { + template + void iter_swap(_It1, _It2) = delete; + + template + concept __adl_iswap + = (std::__detail::__class_or_enum> + || std::__detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + template + constexpr iter_value_t<_Xp> + __iter_exchange_move(_Xp&& __x, _Yp&& __y) + noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x))) + && noexcept(*__x = iter_move(__y))) + { + iter_value_t<_Xp> __old_value(iter_move(__x)); + *__x = iter_move(__y); + return __old_value; + } + + struct _IterSwap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_iswap<_Tp, _Up>) + return noexcept(iter_swap(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + return noexcept(ranges::swap(*std::declval<_Tp>(), + *std::declval<_Up>())); + else + return noexcept(*std::declval<_Tp>() + = __iswap::__iter_exchange_move(std::declval<_Up>(), + std::declval<_Tp>())); + } + + public: + template + requires __adl_iswap<_Tp, _Up> + || (indirectly_readable> + && indirectly_readable> + && swappable_with, iter_reference_t<_Up>>) + || (indirectly_movable_storable<_Tp, _Up> + && indirectly_movable_storable<_Up, _Tp>) + constexpr void + operator()(_Tp&& __e1, _Up&& __e2) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_iswap<_Tp, _Up>) + iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + ranges::swap(*__e1, *__e2); + else + *__e1 = __iswap::__iter_exchange_move(__e2, __e1); + } + }; + } // namespace __iswap + /// @endcond + + inline namespace _Cpo { + inline constexpr __iswap::_IterSwap iter_swap{}; + } + +} // namespace ranges + + /// [alg.req.ind.swap], concept `indirectly_swappable` + template + concept indirectly_swappable + = indirectly_readable<_I1> && indirectly_readable<_I2> + && requires(const _I1 __i1, const _I2 __i2) + { + ranges::iter_swap(__i1, __i1); + ranges::iter_swap(__i2, __i2); + ranges::iter_swap(__i1, __i2); + ranges::iter_swap(__i2, __i1); + }; + + /// [alg.req.ind.cmp], concept `indirectly_comparable` + template + concept indirectly_comparable + = indirect_binary_predicate<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.permutable], concept `permutable` + template + concept permutable = forward_iterator<_Iter> + && indirectly_movable_storable<_Iter, _Iter> + && indirectly_swappable<_Iter, _Iter>; + + /// [alg.req.mergeable], concept `mergeable` + template + concept mergeable = input_iterator<_I1> && input_iterator<_I2> + && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out> + && indirectly_copyable<_I2, _Out> + && indirect_strict_weak_order<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.sortable], concept `sortable` + template + concept sortable = permutable<_Iter> + && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>; + + struct unreachable_sentinel_t + { + template + friend constexpr bool + operator==(unreachable_sentinel_t, const _It&) noexcept + { return false; } + }; + + inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + + // This is the namespace for [range.access] CPOs. + namespace ranges::__access + { + using std::__detail::__class_or_enum; + + struct _Decay_copy final + { + template + constexpr decay_t<_Tp> + operator()(_Tp&& __t) const + noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) + { return std::forward<_Tp>(__t); } + } inline constexpr __decay_copy{}; + + template + concept __member_begin = requires(_Tp& __t) + { + { __decay_copy(__t.begin()) } -> input_or_output_iterator; + }; + + // Poison pill so that unqualified lookup doesn't find std::begin. + void begin() = delete; + + template + concept __adl_begin = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(begin(__t)) } -> input_or_output_iterator; + }; + + // Simplified version of std::ranges::begin that only supports lvalues, + // for use by __range_iter_t below. + template + requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&> + auto + __begin(_Tp& __t) + { + if constexpr (is_array_v<_Tp>) + return __t + 0; + else if constexpr (__member_begin<_Tp&>) + return __t.begin(); + else + return begin(__t); + } + } // namespace ranges::__access + + namespace __detail + { + // Implementation of std::ranges::iterator_t, without using ranges::begin. + template + using __range_iter_t + = decltype(ranges::__access::__begin(std::declval<_Tp&>())); + + } // namespace __detail + +#endif // C++20 library concepts +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _ITERATOR_CONCEPTS_H diff --git a/template/sysroot/include/bits/max_size_type.h b/template/sysroot/include/bits/max_size_type.h new file mode 100644 index 0000000..7d68670 --- /dev/null +++ b/template/sysroot/include/bits/max_size_type.h @@ -0,0 +1,823 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/max_size_type.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _GLIBCXX_MAX_SIZE_TYPE_H +#define _GLIBCXX_MAX_SIZE_TYPE_H 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L && __cpp_lib_concepts +#include +#include + +// This header implements unsigned and signed integer-class types (as per +// [iterator.concept.winc]) that are one bit wider than the widest supported +// integer type. +// +// The set of integer types we consider includes __int128 and unsigned __int128 +// (when they exist), even though they are really integer types only in GNU +// mode. This is to obtain a consistent ABI for these integer-class types +// across strict mode and GNU mode. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template + struct numeric_limits; + +namespace ranges +{ + namespace __detail + { + class __max_size_type + { + public: + __max_size_type() = default; + + template requires integral<_Tp> || __is_int128<_Tp> + constexpr + __max_size_type(_Tp __i) noexcept + : _M_val(__i), _M_msb(__i < 0) + { } + + constexpr explicit + __max_size_type(const __max_diff_type& __d) noexcept; + + template requires integral<_Tp> || __is_int128<_Tp> + constexpr explicit + operator _Tp() const noexcept + { return _M_val; } + + constexpr explicit + operator bool() const noexcept + { return _M_val != 0 || _M_msb != 0; } + + constexpr __max_size_type + operator+() const noexcept + { return *this; } + + constexpr __max_size_type + operator~() const noexcept + { return __max_size_type{~_M_val, !_M_msb}; } + + constexpr __max_size_type + operator-() const noexcept + { return operator~() + 1; } + + constexpr __max_size_type& + operator++() noexcept + { return *this += 1; } + + constexpr __max_size_type + operator++(int) noexcept + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr __max_size_type& + operator--() noexcept + { return *this -= 1; } + + constexpr __max_size_type + operator--(int) noexcept + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr __max_size_type& + operator+=(const __max_size_type& __r) noexcept + { + const auto __sum = _M_val + __r._M_val; + const bool __overflow = (__sum < _M_val); + _M_msb = _M_msb ^ __r._M_msb ^ __overflow; + _M_val = __sum; + return *this; + } + + constexpr __max_size_type& + operator-=(const __max_size_type& __r) noexcept + { return *this += -__r; } + + constexpr __max_size_type& + operator*=(__max_size_type __r) noexcept + { + constexpr __max_size_type __threshold + = __rep(1) << (_S_rep_bits / 2 - 1); + if (_M_val < __threshold && __r < __threshold) + // When both operands are below this threshold then the + // multiplication can be safely computed in the base precision. + _M_val = _M_val * __r._M_val; + else + { + // Otherwise, perform the multiplication in four steps, by + // decomposing the LHS and the RHS into 2*x+a and 2*y+b, + // respectively, and computing 4*x*y + 2*x*b + 2*y*a + a*b. + const bool __lsb = _M_val & 1; + const bool __rlsb = __r._M_val & 1; + *this >>= 1; + __r >>= 1; + _M_val = (2 * _M_val * __r._M_val + + _M_val * __rlsb + __r._M_val * __lsb); + *this <<= 1; + *this += __rlsb * __lsb; + } + + return *this; + } + + constexpr __max_size_type& + operator/=(const __max_size_type& __r) noexcept + { + __glibcxx_assert(__r != 0); + + if (!_M_msb && !__r._M_msb) [[likely]] + _M_val /= __r._M_val; + else if (_M_msb && __r._M_msb) + { + _M_val = (_M_val >= __r._M_val); + _M_msb = 0; + } + else if (!_M_msb && __r._M_msb) + _M_val = 0; + else if (_M_msb && !__r._M_msb) + { + // The non-trivial case: the dividend has its MSB set and the + // divisor doesn't. In this case we compute ((LHS/2)/RHS)*2 + // in the base precision. This quantity is either the true + // quotient or one less than the true quotient. + const auto __orig = *this; + *this >>= 1; + _M_val /= __r._M_val; + *this <<= 1; + if (__orig - *this * __r >= __r) + ++_M_val; + } + return *this; + } + + constexpr __max_size_type& + operator%=(const __max_size_type& __r) noexcept + { + if (!_M_msb && !__r._M_msb) [[likely]] + _M_val %= __r._M_val; + else + *this -= (*this / __r) * __r; + return *this; + } + + constexpr __max_size_type& + operator<<=(const __max_size_type& __r) noexcept + { + __glibcxx_assert(__r <= _S_rep_bits); + if (__r != 0) + { + _M_msb = (_M_val >> (_S_rep_bits - __r._M_val)) & 1; + + if (__r._M_val == _S_rep_bits) [[unlikely]] + _M_val = 0; + else + _M_val <<= __r._M_val; + } + return *this; + } + + constexpr __max_size_type& + operator>>=(const __max_size_type& __r) noexcept + { + __glibcxx_assert(__r <= _S_rep_bits); + if (__r != 0) + { + if (__r._M_val == _S_rep_bits) [[unlikely]] + _M_val = 0; + else + _M_val >>= __r._M_val; + + if (_M_msb) [[unlikely]] + { + _M_val |= __rep(1) << (_S_rep_bits - __r._M_val); + _M_msb = 0; + } + } + return *this; + } + + constexpr __max_size_type& + operator&=(const __max_size_type& __r) noexcept + { + _M_val &= __r._M_val; + _M_msb &= __r._M_msb; + return *this; + } + + constexpr __max_size_type& + operator|=(const __max_size_type& __r) noexcept + { + _M_val |= __r._M_val; + _M_msb |= __r._M_msb; + return *this; + } + + constexpr __max_size_type& + operator^=(const __max_size_type& __r) noexcept + { + _M_val ^= __r._M_val; + _M_msb ^= __r._M_msb; + return *this; + } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator+=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a + __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator-=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a - __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator*=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a * __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator/=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a / __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator%=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a % __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator&=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a & __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator|=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a | __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator^=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a ^ __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator<<=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a << __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator>>=(_Tp& __a, const __max_size_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a >> __b)); } + + friend constexpr __max_size_type + operator+(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l += __r; + return __l; + } + + friend constexpr __max_size_type + operator-(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l -= __r; + return __l; + } + + friend constexpr __max_size_type + operator*(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l *= __r; + return __l; + } + + friend constexpr __max_size_type + operator/(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l /= __r; + return __l; + } + + friend constexpr __max_size_type + operator%(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l %= __r; + return __l; + } + + friend constexpr __max_size_type + operator<<(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l <<= __r; + return __l; + } + + friend constexpr __max_size_type + operator>>(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l >>= __r; + return __l; + } + + friend constexpr __max_size_type + operator&(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l &= __r; + return __l; + } + + friend constexpr __max_size_type + operator|(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l |= __r; + return __l; + } + + friend constexpr __max_size_type + operator^(__max_size_type __l, const __max_size_type& __r) noexcept + { + __l ^= __r; + return __l; + } + + friend constexpr bool + operator==(const __max_size_type& __l, const __max_size_type& __r) noexcept + { return __l._M_val == __r._M_val && __l._M_msb == __r._M_msb; } + +#if __cpp_lib_three_way_comparison + friend constexpr strong_ordering + operator<=>(const __max_size_type& __l, const __max_size_type& __r) noexcept + { + if (__l._M_msb ^ __r._M_msb) + return __l._M_msb ? strong_ordering::greater : strong_ordering::less; + else + return __l._M_val <=> __r._M_val; + } +#else + friend constexpr bool + operator!=(const __max_size_type& __l, const __max_size_type& __r) noexcept + { return !(__l == __r); } + + friend constexpr bool + operator<(const __max_size_type& __l, const __max_size_type& __r) noexcept + { + if (__l._M_msb == __r._M_msb) + return __l._M_val < __r._M_val; + else + return __r._M_msb; + } + + friend constexpr bool + operator>(const __max_size_type& __l, const __max_size_type& __r) noexcept + { return __r < __l; } + + friend constexpr bool + operator<=(const __max_size_type& __l, const __max_size_type& __r) noexcept + { return !(__l > __r); } + + friend constexpr bool + operator>=(const __max_size_type& __l, const __max_size_type& __r) noexcept + { return __r <= __l; } +#endif + +#if __SIZEOF_INT128__ + __extension__ + using __rep = unsigned __int128; +#else + using __rep = unsigned long long; +#endif + static constexpr size_t _S_rep_bits = sizeof(__rep) * __CHAR_BIT__; + private: + __rep _M_val = 0; + unsigned _M_msb:1 = 0; + + constexpr explicit + __max_size_type(__rep __val, int __msb) noexcept + : _M_val(__val), _M_msb(__msb) + { } + + friend __max_diff_type; + friend std::numeric_limits<__max_size_type>; + friend std::numeric_limits<__max_diff_type>; + }; + + class __max_diff_type + { + public: + __max_diff_type() = default; + + template requires integral<_Tp> || __is_int128<_Tp> + constexpr + __max_diff_type(_Tp __i) noexcept + : _M_rep(__i) + { } + + constexpr explicit + __max_diff_type(const __max_size_type& __d) noexcept + : _M_rep(__d) + { } + + template requires integral<_Tp> || __is_int128<_Tp> + constexpr explicit + operator _Tp() const noexcept + { return static_cast<_Tp>(_M_rep); } + + constexpr explicit + operator bool() const noexcept + { return _M_rep != 0; } + + constexpr __max_diff_type + operator+() const noexcept + { return *this; } + + constexpr __max_diff_type + operator-() const noexcept + { return __max_diff_type(-_M_rep); } + + constexpr __max_diff_type + operator~() const noexcept + { return __max_diff_type(~_M_rep); } + + constexpr __max_diff_type& + operator++() noexcept + { return *this += 1; } + + constexpr __max_diff_type + operator++(int) noexcept + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr __max_diff_type& + operator--() noexcept + { return *this -= 1; } + + constexpr __max_diff_type + operator--(int) noexcept + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr __max_diff_type& + operator+=(const __max_diff_type& __r) noexcept + { + _M_rep += __r._M_rep; + return *this; + } + + constexpr __max_diff_type& + operator-=(const __max_diff_type& __r) noexcept + { + _M_rep -= __r._M_rep; + return *this; + } + + constexpr __max_diff_type& + operator*=(const __max_diff_type& __r) noexcept + { + _M_rep *= __r._M_rep; + return *this; + } + + constexpr __max_diff_type& + operator/=(const __max_diff_type& __r) noexcept + { + __glibcxx_assert (__r != 0); + const bool __neg = *this < 0; + const bool __rneg = __r < 0; + if (!__neg && !__rneg) + _M_rep = _M_rep / __r._M_rep; + else if (__neg && __rneg) + _M_rep = -_M_rep / -__r._M_rep; + else if (__neg && !__rneg) + _M_rep = -(-_M_rep / __r._M_rep); + else + _M_rep = -(_M_rep / -__r._M_rep); + return *this ; + } + + constexpr __max_diff_type& + operator%=(const __max_diff_type& __r) noexcept + { + __glibcxx_assert (__r != 0); + if (*this >= 0 && __r > 0) + _M_rep %= __r._M_rep; + else + *this -= (*this / __r) * __r; + return *this; + } + + constexpr __max_diff_type& + operator<<=(const __max_diff_type& __r) noexcept + { + _M_rep.operator<<=(__r._M_rep); + return *this; + } + + constexpr __max_diff_type& + operator>>=(const __max_diff_type& __r) noexcept + { + // Arithmetic right shift. + const auto __msb = _M_rep._M_msb; + _M_rep >>= __r._M_rep; + if (__msb) + _M_rep |= ~(__max_size_type(-1) >> __r._M_rep); + return *this; + } + + constexpr __max_diff_type& + operator&=(const __max_diff_type& __r) noexcept + { + _M_rep &= __r._M_rep; + return *this; + } + + constexpr __max_diff_type& + operator|=(const __max_diff_type& __r) noexcept + { + _M_rep |= __r._M_rep; + return *this; + } + + constexpr __max_diff_type& + operator^=(const __max_diff_type& __r) noexcept + { + _M_rep ^= __r._M_rep; + return *this; + } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator+=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a + __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator-=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a - __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator*=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a * __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator/=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a / __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator%=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a % __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator&=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a & __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator|=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a | __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator^=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a ^ __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator<<=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a << __b)); } + + template requires integral<_Tp> || __is_int128<_Tp> + friend constexpr _Tp& + operator>>=(_Tp& __a, const __max_diff_type& __b) noexcept + { return (__a = static_cast<_Tp>(__a >> __b)); } + + friend constexpr __max_diff_type + operator+(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l += __r; + return __l; + } + + friend constexpr __max_diff_type + operator-(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l -= __r; + return __l; + } + + friend constexpr __max_diff_type + operator*(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l *= __r; + return __l; + } + + friend constexpr __max_diff_type + operator/(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l /= __r; + return __l; + } + + friend constexpr __max_diff_type + operator%(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l %= __r; + return __l; + } + + friend constexpr __max_diff_type + operator<<(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l <<= __r; + return __l; + } + + friend constexpr __max_diff_type + operator>>(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l >>= __r; + return __l; + } + + friend constexpr __max_diff_type + operator&(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l &= __r; + return __l; + } + + friend constexpr __max_diff_type + operator|(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l |= __r; + return __l; + } + + friend constexpr __max_diff_type + operator^(__max_diff_type __l, const __max_diff_type& __r) noexcept + { + __l ^= __r; + return __l; + } + + friend constexpr bool + operator==(const __max_diff_type& __l, const __max_diff_type& __r) noexcept + { return __l._M_rep == __r._M_rep; } + +#if __cpp_lib_three_way_comparison + constexpr strong_ordering + operator<=>(const __max_diff_type& __r) const noexcept + { + const auto __lsign = _M_rep._M_msb; + const auto __rsign = __r._M_rep._M_msb; + if (__lsign ^ __rsign) + return __lsign ? strong_ordering::less : strong_ordering::greater; + else + return _M_rep <=> __r._M_rep; + } +#else + friend constexpr bool + operator!=(const __max_diff_type& __l, const __max_diff_type& __r) noexcept + { return !(__l == __r); } + + constexpr bool + operator<(const __max_diff_type& __r) const noexcept + { + const auto __lsign = _M_rep._M_msb; + const auto __rsign = __r._M_rep._M_msb; + if (__lsign ^ __rsign) + return __lsign; + else + return _M_rep < __r._M_rep; + } + + friend constexpr bool + operator>(const __max_diff_type& __l, const __max_diff_type& __r) noexcept + { return __r < __l; } + + friend constexpr bool + operator<=(const __max_diff_type& __l, const __max_diff_type& __r) noexcept + { return !(__r < __l); } + + friend constexpr bool + operator>=(const __max_diff_type& __l, const __max_diff_type& __r) noexcept + { return !(__l < __r); } +#endif + + private: + __max_size_type _M_rep = 0; + + friend class __max_size_type; + }; + + constexpr + __max_size_type::__max_size_type(const __max_diff_type& __d) noexcept + : __max_size_type(__d._M_rep) + { } + + } // namespace __detail +} // namespace ranges + + template<> + struct numeric_limits + { + using _Sp = ranges::__detail::__max_size_type; + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int digits + = __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1; + static constexpr int digits10 + = static_cast(digits * numbers::ln2 / numbers::ln10); + + static constexpr _Sp + min() noexcept + { return 0; } + + static constexpr _Sp + max() noexcept + { return _Sp(static_cast<_Sp::__rep>(-1), 1); } + + static constexpr _Sp + lowest() noexcept + { return min(); } + }; + + template<> + struct numeric_limits + { + using _Dp = ranges::__detail::__max_diff_type; + using _Sp = ranges::__detail::__max_size_type; + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int digits = numeric_limits<_Sp>::digits - 1; + static constexpr int digits10 + = static_cast(digits * numbers::ln2 / numbers::ln10); + + static constexpr _Dp + min() noexcept + { return _Dp(_Sp(0, 1)); } + + static constexpr _Dp + max() noexcept + { return _Dp(_Sp(static_cast<_Sp::__rep>(-1), 0)); } + + static constexpr _Dp + lowest() noexcept + { return min(); } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++20 && library concepts +#endif // _GLIBCXX_MAX_SIZE_TYPE_H diff --git a/template/sysroot/include/bits/memoryfwd.h b/template/sysroot/include/bits/memoryfwd.h new file mode 100644 index 0000000..03d1162 --- /dev/null +++ b/template/sysroot/include/bits/memoryfwd.h @@ -0,0 +1,84 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/memoryfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _MEMORYFWD_H +#define _MEMORYFWD_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup allocators Allocators + * @ingroup memory + * + * Classes encapsulating memory operations. + * + * @{ + */ + + // Included in freestanding as a libstdc++ extension. + template + class allocator; + + template<> + class allocator; + +#if __cplusplus >= 201103L + /// Declare uses_allocator so it can be specialized in `` etc. + template + struct uses_allocator; + + template + struct allocator_traits; +#endif + + /// @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/template/sysroot/include/bits/messages_members.h b/template/sysroot/include/bits/messages_members.h new file mode 100644 index 0000000..e100763 --- /dev/null +++ b/template/sysroot/include/bits/messages_members.h @@ -0,0 +1,92 @@ +// std::messages implementation details, generic version -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/messages_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.2.7.1.2 messages virtual functions +// + +// Written by Benjamin Kosnik + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Non-virtual member functions. + template + messages<_CharT>::messages(size_t __refs) + : facet(__refs) + { _M_c_locale_messages = _S_get_c_locale(); } + + template + messages<_CharT>::messages(__c_locale, const char*, size_t __refs) + : facet(__refs) + { _M_c_locale_messages = _S_get_c_locale(); } + + template + typename messages<_CharT>::catalog + messages<_CharT>::open(const basic_string& __s, const locale& __loc, + const char*) const + { return this->do_open(__s, __loc); } + + // Virtual member functions. + template + messages<_CharT>::~messages() + { _S_destroy_c_locale(_M_c_locale_messages); } + + template + typename messages<_CharT>::catalog + messages<_CharT>::do_open(const basic_string&, const locale&) const + { return 0; } + + template + typename messages<_CharT>::string_type + messages<_CharT>::do_get(catalog, int, int, + const string_type& __dfault) const + { return __dfault; } + + template + void + messages<_CharT>::do_close(catalog) const + { } + + // messages_byname + template + messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs) + : messages<_CharT>(__refs) + { + if (__builtin_strcmp(__s, "C") != 0 + && __builtin_strcmp(__s, "POSIX") != 0) + { + this->_S_destroy_c_locale(this->_M_c_locale_messages); + this->_S_create_c_locale(this->_M_c_locale_messages, __s); + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/template/sysroot/include/bits/move.h b/template/sysroot/include/bits/move.h new file mode 100644 index 0000000..bb200c9 --- /dev/null +++ b/template/sysroot/include/bits/move.h @@ -0,0 +1,248 @@ +// Move, forward and identity for C++11 + swap -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/move.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _MOVE_H +#define _MOVE_H 1 + +#include +#if __cplusplus < 201103L +# include +#else +# include // Brings in std::declval too. +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Used, in C++03 mode too, by allocators, etc. + /** + * @brief Same as C++11 std::addressof + * @ingroup utilities + */ + template + inline _GLIBCXX_CONSTEXPR _Tp* + __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT + { return __builtin_addressof(__r); } + +#if __cplusplus >= 201103L + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Forward an lvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + _GLIBCXX_NODISCARD + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Tp&&>(__t); } + + /** + * @brief Forward an rvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + _GLIBCXX_NODISCARD + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type&& __t) noexcept + { + static_assert(!std::is_lvalue_reference<_Tp>::value, + "std::forward must not be used to convert an rvalue to an lvalue"); + return static_cast<_Tp&&>(__t); + } + +#if __glibcxx_forward_like // C++ >= 23 + template + [[nodiscard]] + constexpr decltype(auto) + forward_like(_Up&& __x) noexcept + { + constexpr bool __as_rval = is_rvalue_reference_v<_Tp&&>; + + if constexpr (is_const_v>) + { + using _Up2 = remove_reference_t<_Up>; + if constexpr (__as_rval) + return static_cast(__x); + else + return static_cast(__x); + } + else + { + if constexpr (__as_rval) + return static_cast&&>(__x); + else + return static_cast<_Up&>(__x); + } + } + + template + using __like_t = decltype(std::forward_like<_Tp>(std::declval<_Up>())); +#endif + + /** + * @brief Convert a value to an rvalue. + * @param __t A thing of arbitrary type. + * @return The parameter cast to an rvalue-reference to allow moving it. + */ + template + _GLIBCXX_NODISCARD + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast::type&&>(__t); } + + + template + struct __move_if_noexcept_cond + : public __and_<__not_>, + is_copy_constructible<_Tp>>::type { }; + + /** + * @brief Conditionally convert a value to an rvalue. + * @param __x A thing of arbitrary type. + * @return The parameter, possibly cast to an rvalue-reference. + * + * Same as std::move unless the type's move constructor could throw and the + * type is copyable, in which case an lvalue-reference is returned instead. + */ + template + _GLIBCXX_NODISCARD + constexpr + __conditional_t<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&> + move_if_noexcept(_Tp& __x) noexcept + { return std::move(__x); } + + // declval, from type_traits. + + /** + * @brief Returns the actual address of the object or function + * referenced by r, even in the presence of an overloaded + * operator&. + * @param __r Reference to an object or function. + * @return The actual address. + */ + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR _Tp* + addressof(_Tp& __r) noexcept + { return std::__addressof(__r); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2598. addressof works on temporaries + template + const _Tp* addressof(const _Tp&&) = delete; + + // C++11 version of std::exchange for internal use. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + __exchange(_Tp& __obj, _Up&& __new_val) + { + _Tp __old_val = std::move(__obj); + __obj = std::forward<_Up>(__new_val); + return __old_val; + } + + /// @} group utilities + +#define _GLIBCXX_FWDREF(_Tp) _Tp&& +#define _GLIBCXX_MOVE(__val) std::move(__val) +#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) +#else +#define _GLIBCXX_FWDREF(_Tp) const _Tp& +#define _GLIBCXX_MOVE(__val) (__val) +#define _GLIBCXX_FORWARD(_Tp, __val) (__val) +#endif + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Swaps two values. + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return Nothing. + */ + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else + void +#endif + swap(_Tp& __a, _Tp& __b) + _GLIBCXX_NOEXCEPT_IF(__and_, + is_nothrow_move_assignable<_Tp>>::value) + { +#if __cplusplus < 201103L + // concept requirements + __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) +#endif + _Tp __tmp = _GLIBCXX_MOVE(__a); + __a = _GLIBCXX_MOVE(__b); + __b = _GLIBCXX_MOVE(__tmp); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 809. std::swap should be overloaded for array types. + /// Swap the contents of two arrays. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__is_swappable<_Tp>::value>::type +#else + void +#endif + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value) + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } + + /// @} group utilities +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _MOVE_H */ diff --git a/template/sysroot/include/bits/nested_exception.h b/template/sysroot/include/bits/nested_exception.h new file mode 100644 index 0000000..3c9392f --- /dev/null +++ b/template/sysroot/include/bits/nested_exception.h @@ -0,0 +1,243 @@ +// Nested Exception support header (nested_exception class) for -*- C++ -*- + +// Copyright (C) 2009-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/nested_exception.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + */ + +#ifndef _GLIBCXX_NESTED_EXCEPTION_H +#define _GLIBCXX_NESTED_EXCEPTION_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ + /** + * @addtogroup exceptions + * @{ + */ + + /** Mixin class that stores the current exception. + * + * This type can be used via `std::throw_with_nested` to store + * the current exception nested within another exception. + * + * @headerfile exception + * @since C++11 + * @see std::throw_with_nested + * @ingroup exceptions + */ + class nested_exception + { + exception_ptr _M_ptr; + + public: + /// The default constructor stores the current exception (if any). + nested_exception() noexcept : _M_ptr(current_exception()) { } + + nested_exception(const nested_exception&) noexcept = default; + + nested_exception& operator=(const nested_exception&) noexcept = default; + + virtual ~nested_exception() noexcept; + + /// Rethrow the stored exception, or terminate if none was stored. + [[noreturn]] + void + rethrow_nested() const + { + if (_M_ptr) + rethrow_exception(_M_ptr); + std::terminate(); + } + + /// Access the stored exception. + exception_ptr + nested_ptr() const noexcept + { return _M_ptr; } + }; + + /// @cond undocumented + + template + struct _Nested_exception : public _Except, public nested_exception + { + explicit _Nested_exception(const _Except& __ex) + : _Except(__ex) + { } + + explicit _Nested_exception(_Except&& __ex) + : _Except(static_cast<_Except&&>(__ex)) + { } + }; + +#if __cplusplus < 201703L || ! defined __cpp_if_constexpr + // [except.nested]/8 + // Throw an exception of unspecified type that is publicly derived from + // both remove_reference_t<_Tp> and nested_exception. + template + [[noreturn]] + inline void + __throw_with_nested_impl(_Tp&& __t, true_type) + { + throw _Nested_exception<__remove_cvref_t<_Tp>>{std::forward<_Tp>(__t)}; + } + + template + [[noreturn]] + inline void + __throw_with_nested_impl(_Tp&& __t, false_type) + { throw std::forward<_Tp>(__t); } +#endif + + /// @endcond + + /** Throw an exception that also stores the currently active exception. + * + * If `_Tp` is derived from `std::nested_exception` or is not usable + * as a base-class, throws a copy of `__t`. + * Otherwise, throws an object of an implementation-defined type derived + * from both `_Tp` and `std::nested_exception`, containing a copy of `__t` + * and the result of `std::current_exception()`. + * + * In other words, throws the argument as a new exception that contains + * the currently active exception nested within it. This is intended for + * use in a catch handler to replace the caught exception with a different + * type, while still preserving the original exception. When the new + * exception is caught, the nested exception can be rethrown by using + * `std::rethrow_if_nested`. + * + * This can be used at API boundaries, for example to catch a library's + * internal exception type and rethrow it nested with a `std::runtime_error`, + * or vice versa. + * + * @since C++11 + */ + template + [[noreturn]] + inline void + throw_with_nested(_Tp&& __t) + { + using _Up = typename decay<_Tp>::type; + using _CopyConstructible + = __and_, is_move_constructible<_Up>>; + static_assert(_CopyConstructible::value, + "throw_with_nested argument must be CopyConstructible"); + +#if __cplusplus >= 201703L && __cpp_if_constexpr + if constexpr (is_class_v<_Up>) + if constexpr (!is_final_v<_Up>) + if constexpr (!is_base_of_v) + throw _Nested_exception<_Up>{std::forward<_Tp>(__t)}; + throw std::forward<_Tp>(__t); +#else + using __nest = __and_, __bool_constant, + __not_>>; + std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); +#endif + } + +#if __cplusplus < 201703L || ! defined __cpp_if_constexpr + /// @cond undocumented + + // Attempt dynamic_cast to nested_exception and call rethrow_nested(). + template + inline void + __rethrow_if_nested_impl(const _Ex* __ptr, true_type) + { + if (auto __ne_ptr = dynamic_cast(__ptr)) + __ne_ptr->rethrow_nested(); + } + + // Otherwise, no effects. + inline void + __rethrow_if_nested_impl(const void*, false_type) + { } + + /// @endcond +#endif + + /** Rethrow a nested exception + * + * If `__ex` contains a `std::nested_exception` object, call its + * `rethrow_nested()` member to rethrow the stored exception. + * + * After catching an exception thrown by a call to `std::throw_with_nested` + * this function can be used to rethrow the exception that was active when + * `std::throw_with_nested` was called. + * + * @since C++11 + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2484. rethrow_if_nested() is doubly unimplementable + // 2784. Resolution to LWG 2484 is missing "otherwise, no effects" and [...] + template +# if ! __cpp_rtti + [[__gnu__::__always_inline__]] +#endif + inline void + rethrow_if_nested(const _Ex& __ex) + { + const _Ex* __ptr = __builtin_addressof(__ex); +#if __cplusplus < 201703L || ! defined __cpp_if_constexpr +# if __cpp_rtti + using __cast = __and_, + __or_<__not_>, + is_convertible<_Ex*, nested_exception*>>>; +# else + using __cast = __and_, + is_base_of, + is_convertible<_Ex*, nested_exception*>>; +# endif + std::__rethrow_if_nested_impl(__ptr, __cast{}); +#else + if constexpr (!is_polymorphic_v<_Ex>) + return; + else if constexpr (is_base_of_v + && !is_convertible_v<_Ex*, nested_exception*>) + return; // nested_exception base class is inaccessible or ambiguous. +# if ! __cpp_rtti + else if constexpr (!is_base_of_v) + return; // Cannot do polymorphic casts without RTTI. +# endif + else if (auto __ne_ptr = dynamic_cast(__ptr)) + __ne_ptr->rethrow_nested(); +#endif + } + + /// @} group exceptions +} // namespace std + +} // extern "C++" + +#endif // C++11 +#endif // _GLIBCXX_NESTED_EXCEPTION_H diff --git a/template/sysroot/include/bits/opt_random.h b/template/sysroot/include/bits/opt_random.h new file mode 100644 index 0000000..154315d --- /dev/null +++ b/template/sysroot/include/bits/opt_random.h @@ -0,0 +1,221 @@ +// Optimizations for random number functions, x86 version -*- C++ -*- + +// Copyright (C) 2012-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/opt_random.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _BITS_OPT_RANDOM_H +#define _BITS_OPT_RANDOM_H 1 + +#ifdef __SSE3__ +#include +#endif + + +#pragma GCC system_header + + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __SSE3__ + template<> + template + void + normal_distribution:: + __generate(typename normal_distribution::result_type* __f, + typename normal_distribution::result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + typedef uint64_t __uctype; + + if (__f == __t) + return; + + if (_M_saved_available) + { + _M_saved_available = false; + *__f++ = _M_saved * __param.stddev() + __param.mean(); + + if (__f == __t) + return; + } + + constexpr uint64_t __maskval = 0xfffffffffffffull; + static const __m128i __mask = _mm_set1_epi64x(__maskval); + static const __m128i __two = _mm_set1_epi64x(0x4000000000000000ull); + static const __m128d __three = _mm_set1_pd(3.0); + const __m128d __av = _mm_set1_pd(__param.mean()); + + const __uctype __urngmin = __urng.min(); + const __uctype __urngmax = __urng.max(); + const __uctype __urngrange = __urngmax - __urngmin; + const __uctype __uerngrange = __urngrange + 1; + + while (__f + 1 < __t) + { + double __le; + __m128d __x; + do + { + union + { + __m128i __i; + __m128d __d; + } __v; + + if (__urngrange > __maskval) + { + if (__detail::_Power_of_2(__uerngrange)) + __v.__i = _mm_and_si128(_mm_set_epi64x(__urng(), + __urng()), + __mask); + else + { + const __uctype __uerange = __maskval + 1; + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + uint64_t __v1; + do + __v1 = __uctype(__urng()) - __urngmin; + while (__v1 >= __past); + __v1 /= __scaling; + uint64_t __v2; + do + __v2 = __uctype(__urng()) - __urngmin; + while (__v2 >= __past); + __v2 /= __scaling; + + __v.__i = _mm_set_epi64x(__v1, __v2); + } + } + else if (__urngrange == __maskval) + __v.__i = _mm_set_epi64x(__urng(), __urng()); + else if ((__urngrange + 2) * __urngrange >= __maskval + && __detail::_Power_of_2(__uerngrange)) + { + uint64_t __v1 = __urng() * __uerngrange + __urng(); + uint64_t __v2 = __urng() * __uerngrange + __urng(); + + __v.__i = _mm_and_si128(_mm_set_epi64x(__v1, __v2), + __mask); + } + else + { + size_t __nrng = 2; + __uctype __high = __maskval / __uerngrange / __uerngrange; + while (__high > __uerngrange) + { + ++__nrng; + __high /= __uerngrange; + } + const __uctype __highrange = __high + 1; + const __uctype __scaling = __urngrange / __highrange; + const __uctype __past = __highrange * __scaling; + __uctype __tmp; + + uint64_t __v1; + do + { + do + __tmp = __uctype(__urng()) - __urngmin; + while (__tmp >= __past); + __v1 = __tmp / __scaling; + for (size_t __cnt = 0; __cnt < __nrng; ++__cnt) + { + __tmp = __v1; + __v1 *= __uerngrange; + __v1 += __uctype(__urng()) - __urngmin; + } + } + while (__v1 > __maskval || __v1 < __tmp); + + uint64_t __v2; + do + { + do + __tmp = __uctype(__urng()) - __urngmin; + while (__tmp >= __past); + __v2 = __tmp / __scaling; + for (size_t __cnt = 0; __cnt < __nrng; ++__cnt) + { + __tmp = __v2; + __v2 *= __uerngrange; + __v2 += __uctype(__urng()) - __urngmin; + } + } + while (__v2 > __maskval || __v2 < __tmp); + + __v.__i = _mm_set_epi64x(__v1, __v2); + } + + __v.__i = _mm_or_si128(__v.__i, __two); + __x = _mm_sub_pd(__v.__d, __three); + __m128d __m = _mm_mul_pd(__x, __x); + __le = _mm_cvtsd_f64(_mm_hadd_pd (__m, __m)); + } + while (__le == 0.0 || __le >= 1.0); + + double __mult = (std::sqrt(-2.0 * std::log(__le) / __le) + * __param.stddev()); + + __x = _mm_add_pd(_mm_mul_pd(__x, _mm_set1_pd(__mult)), __av); + + _mm_storeu_pd(__f, __x); + __f += 2; + } + + if (__f != __t) + { + result_type __x, __y, __r2; + + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + *__f = __y * __mult * __param.stddev() + __param.mean(); + } + } +#endif + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#endif // _BITS_OPT_RANDOM_H diff --git a/template/sysroot/include/bits/os_defines.h b/template/sysroot/include/bits/os_defines.h new file mode 100644 index 0000000..3e5ad80 --- /dev/null +++ b/template/sysroot/include/bits/os_defines.h @@ -0,0 +1,41 @@ +// Specific definitions for generic platforms -*- C++ -*- + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/os_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _GLIBCXX_OS_DEFINES +#define _GLIBCXX_OS_DEFINES 1 + +// System-specific #define, typedefs, corrections, etc, go here. This +// file will come before all others. + +// Disable the weak reference logic in gthr.h for os/generic because it +// is broken on every platform unless there is implementation specific +// workaround in gthr-posix.h and at link-time for static linking. +#define _GLIBCXX_GTHREAD_USE_WEAK 0 + +#endif diff --git a/template/sysroot/include/bits/out_ptr.h b/template/sysroot/include/bits/out_ptr.h new file mode 100644 index 0000000..d74c9f5 --- /dev/null +++ b/template/sysroot/include/bits/out_ptr.h @@ -0,0 +1,473 @@ +// Smart pointer adaptors -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/out_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_OUT_PTR_H +#define _GLIBCXX_OUT_PTR_H 1 + +#pragma GCC system_header + +#include + +#ifdef __glibcxx_out_ptr // C++ >= 23 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Smart pointer adaptor for functions taking an output pointer parameter. + /** + * @tparam _Smart The type of pointer to adapt. + * @tparam _Pointer The type of pointer to convert to. + * @tparam _Args... Argument types used when resetting the smart pointer. + * @since C++23 + * @headerfile + */ + template + class out_ptr_t + { +#if _GLIBCXX_HOSTED + static_assert(!__is_shared_ptr<_Smart> || sizeof...(_Args) != 0, + "a deleter must be used when adapting std::shared_ptr " + "with std::out_ptr"); +#endif + + public: + explicit + out_ptr_t(_Smart& __smart, _Args... __args) + : _M_impl{__smart, std::forward<_Args>(__args)...} + { + if constexpr (requires { _M_impl._M_out_init(); }) + _M_impl._M_out_init(); + } + + out_ptr_t(const out_ptr_t&) = delete; + + ~out_ptr_t() = default; + + operator _Pointer*() const noexcept + { return _M_impl._M_get(); } + + operator void**() const noexcept requires (!same_as<_Pointer, void*>) + { + static_assert(is_pointer_v<_Pointer>); + _Pointer* __p = *this; + return static_cast(static_cast(__p)); + } + + private: + // TODO: Move this to namespace scope? e.g. __detail::_Ptr_adapt_impl + template + struct _Impl + { + // This constructor must not modify __s because out_ptr_t and + // inout_ptr_t want to do different things. After construction + // they call _M_out_init() or _M_inout_init() respectively. + _Impl(_Smart& __s, _Args&&... __args) + : _M_smart(__s), _M_args(std::forward<_Args>(__args)...) + { } + + // Called by out_ptr_t to clear the smart pointer before using it. + void + _M_out_init() + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3734. Inconsistency in inout_ptr and out_ptr for empty case + if constexpr (requires { _M_smart.reset(); }) + _M_smart.reset(); + else + _M_smart = _Smart(); + } + + // Called by inout_ptr_t to copy the smart pointer's value + // to the pointer that is returned from _M_get(). + void + _M_inout_init() + { _M_ptr = _M_smart.release(); } + + // The pointer value returned by operator Pointer*(). + _Pointer* + _M_get() const + { return __builtin_addressof(const_cast<_Pointer&>(_M_ptr)); } + + // Finalize the effects on the smart pointer. + ~_Impl() noexcept(false); + + _Smart& _M_smart; + [[no_unique_address]] _Pointer _M_ptr{}; + [[no_unique_address]] tuple<_Args...> _M_args; + }; + + // Partial specialization for raw pointers. + template + struct _Impl<_Tp*, _Tp*> + { + void + _M_out_init() + { _M_p = nullptr; } + + void + _M_inout_init() + { } + + _Tp** + _M_get() const + { return __builtin_addressof(const_cast<_Tp*&>(_M_p)); } + + _Tp*& _M_p; + }; + + // Partial specialization for raw pointers, with conversion. + template requires (!is_same_v<_Ptr, _Tp*>) + struct _Impl<_Tp*, _Ptr> + { + explicit + _Impl(_Tp*& __p) + : _M_p(__p) + { } + + void + _M_out_init() + { _M_p = nullptr; } + + void + _M_inout_init() + { _M_ptr = _M_p; } + + _Pointer* + _M_get() const + { return __builtin_addressof(const_cast<_Pointer&>(_M_ptr)); } + + ~_Impl() { _M_p = static_cast<_Tp*>(_M_ptr); } + + _Tp*& _M_p; + _Pointer _M_ptr{}; + }; + + // Partial specialization for std::unique_ptr. + // This specialization gives direct access to the private member + // of the unique_ptr, avoiding the overhead of storing a separate + // pointer and then resetting the unique_ptr in the destructor. + // FIXME: constrain to only match the primary template, + // not program-defined specializations of unique_ptr. + template + struct _Impl, + typename unique_ptr<_Tp, _Del>::pointer> + { + void + _M_out_init() + { _M_smart.reset(); } + + _Pointer* + _M_get() const noexcept + { return __builtin_addressof(_M_smart._M_t._M_ptr()); } + + _Smart& _M_smart; + }; + + // Partial specialization for std::unique_ptr with replacement deleter. + // FIXME: constrain to only match the primary template, + // not program-defined specializations of unique_ptr. + template + struct _Impl, + typename unique_ptr<_Tp, _Del>::pointer, _Del2> + { + void + _M_out_init() + { _M_smart.reset(); } + + _Pointer* + _M_get() const noexcept + { return __builtin_addressof(_M_smart._M_t._M_ptr()); } + + ~_Impl() + { + if (_M_smart.get()) + _M_smart._M_t._M_deleter() = std::forward<_Del2>(_M_del); + } + + _Smart& _M_smart; + [[no_unique_address]] _Del2 _M_del; + }; + +#if _GLIBCXX_HOSTED + // Partial specialization for std::shared_ptr. + // This specialization gives direct access to the private member + // of the shared_ptr, avoiding the overhead of storing a separate + // pointer and then resetting the shared_ptr in the destructor. + // A new control block is allocated in the constructor, so that if + // allocation fails it doesn't throw an exception from the destructor. + template + requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>) + struct _Impl, + typename shared_ptr<_Tp>::element_type*, _Del, _Alloc> + { + _Impl(_Smart& __s, _Del __d, _Alloc __a = _Alloc()) + : _M_smart(__s) + { + // We know shared_ptr cannot be used with inout_ptr_t + // so we can do all set up here, instead of in _M_out_init(). + _M_smart.reset(); + + // Similar to the shared_ptr(Y*, D, A) constructor, except that if + // the allocation throws we do not need (or want) to call deleter. + typename _Scd::__allocator_type __a2(__a); + auto __mem = __a2.allocate(1); + ::new (__mem) _Scd(nullptr, std::forward<_Del>(__d), + std::forward<_Alloc>(__a)); + _M_smart._M_refcount._M_pi = __mem; + } + + _Pointer* + _M_get() const noexcept + { return __builtin_addressof(_M_smart._M_ptr); } + + ~_Impl() + { + auto& __pi = _M_smart._M_refcount._M_pi; + + if (_Sp __ptr = _M_smart.get()) + static_cast<_Scd*>(__pi)->_M_impl._M_ptr = __ptr; + else // Destroy the control block manually without invoking deleter. + std::__exchange(__pi, nullptr)->_M_destroy(); + } + + _Smart& _M_smart; + + using _Sp = typename _Smart::element_type*; + using _Scd = _Sp_counted_deleter<_Sp, decay_t<_Del>, + remove_cvref_t<_Alloc>, + __default_lock_policy>; + }; + + // Partial specialization for std::shared_ptr, without custom allocator. + template + requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>) + struct _Impl, + typename shared_ptr<_Tp>::element_type*, _Del> + : _Impl<_Smart, _Pointer, _Del, allocator> + { + using _Impl<_Smart, _Pointer, _Del, allocator>::_Impl; + }; +#endif + + using _Impl_t = _Impl<_Smart, _Pointer, _Args...>; + + _Impl_t _M_impl; + + template friend class inout_ptr_t; + }; + + /// Smart pointer adaptor for functions taking an inout pointer parameter. + /** + * @tparam _Smart The type of pointer to adapt. + * @tparam _Pointer The type of pointer to convert to. + * @tparam _Args... Argument types used when resetting the smart pointer. + * @since C++23 + * @headerfile + */ + template + class inout_ptr_t + { +#if _GLIBCXX_HOSTED + static_assert(!__is_shared_ptr<_Smart>, + "std::inout_ptr can not be used to wrap std::shared_ptr"); +#endif + + public: + explicit + inout_ptr_t(_Smart& __smart, _Args... __args) + : _M_impl{__smart, std::forward<_Args>(__args)...} + { + if constexpr (requires { _M_impl._M_inout_init(); }) + _M_impl._M_inout_init(); + } + + inout_ptr_t(const inout_ptr_t&) = delete; + + ~inout_ptr_t() = default; + + operator _Pointer*() const noexcept + { return _M_impl._M_get(); } + + operator void**() const noexcept requires (!same_as<_Pointer, void*>) + { + static_assert(is_pointer_v<_Pointer>); + _Pointer* __p = *this; + return static_cast(static_cast(__p)); + } + + private: +#if _GLIBCXX_HOSTED + // Avoid an invalid instantiation of out_ptr_t, ...> + using _Out_ptr_t + = __conditional_t<__is_shared_ptr<_Smart>, + out_ptr_t, + out_ptr_t<_Smart, _Pointer, _Args...>>; +#else + using _Out_ptr_t = out_ptr_t<_Smart, _Pointer, _Args...>; +#endif + using _Impl_t = typename _Out_ptr_t::_Impl_t; + _Impl_t _M_impl; + }; + +/// @cond undocumented +namespace __detail +{ + // POINTER_OF metafunction + template + consteval auto + __pointer_of() + { + if constexpr (requires { typename _Tp::pointer; }) + return type_identity{}; + else if constexpr (requires { typename _Tp::element_type; }) + return type_identity{}; + else + { + using _Traits = pointer_traits<_Tp>; + if constexpr (requires { typename _Traits::element_type; }) + return type_identity{}; + } + // else POINTER_OF(S) is not a valid type, return void. + } + + // POINTER_OF_OR metafunction + template + consteval auto + __pointer_of_or() + { + using _TypeId = decltype(__detail::__pointer_of<_Smart>()); + if constexpr (is_void_v<_TypeId>) + return type_identity<_Ptr>{}; + else + return _TypeId{}; + } + + // Returns Pointer if !is_void_v, otherwise POINTER_OF(Smart). + template + consteval auto + __choose_ptr() + { + if constexpr (!is_void_v<_Ptr>) + return type_identity<_Ptr>{}; + else + return __detail::__pointer_of<_Smart>(); + } + + template + concept __resettable = requires (_Smart& __s) { + __s.reset(std::declval<_Sp>(), std::declval<_Args>()...); + }; +} +/// @endcond + + /// Adapt a smart pointer for functions taking an output pointer parameter. + /** + * @tparam _Pointer The type of pointer to convert to. + * @param __s The pointer that should take ownership of the result. + * @param __args... Arguments to use when resetting the smart pointer. + * @return A std::inout_ptr_t referring to `__s`. + * @since C++23 + * @headerfile + */ + template + inline auto + out_ptr(_Smart& __s, _Args&&... __args) + { + using _TypeId = decltype(__detail::__choose_ptr<_Pointer, _Smart>()); + static_assert(!is_void_v<_TypeId>, "first argument to std::out_ptr " + "must be a pointer-like type"); + + using _Ret = out_ptr_t<_Smart, typename _TypeId::type, _Args&&...>; + return _Ret(__s, std::forward<_Args>(__args)...); + } + + /// Adapt a smart pointer for functions taking an inout pointer parameter. + /** + * @tparam _Pointer The type of pointer to convert to. + * @param __s The pointer that should take ownership of the result. + * @param __args... Arguments to use when resetting the smart pointer. + * @return A std::inout_ptr_t referring to `__s`. + * @since C++23 + * @headerfile + */ + template + inline auto + inout_ptr(_Smart& __s, _Args&&... __args) + { + using _TypeId = decltype(__detail::__choose_ptr<_Pointer, _Smart>()); + static_assert(!is_void_v<_TypeId>, "first argument to std::inout_ptr " + "must be a pointer-like type"); + + using _Ret = inout_ptr_t<_Smart, typename _TypeId::type, _Args&&...>; + return _Ret(__s, std::forward<_Args>(__args)...); + } + + /// @cond undocumented + template + template + inline + out_ptr_t<_Smart, _Pointer, _Args...>:: + _Impl<_Smart2, _Pointer2, _Args2...>::~_Impl() + { + using _TypeId = decltype(__detail::__pointer_of_or<_Smart, _Pointer>()); + using _Sp = typename _TypeId::type; + + if (!_M_ptr) + return; + + _Smart& __s = _M_smart; + _Pointer& __p = _M_ptr; + + auto __reset = [&](auto&&... __args) { + if constexpr (__detail::__resettable<_Smart, _Sp, _Args...>) + __s.reset(static_cast<_Sp>(__p), std::forward<_Args>(__args)...); + else if constexpr (is_constructible_v<_Smart, _Sp, _Args...>) + __s = _Smart(static_cast<_Sp>(__p), std::forward<_Args>(__args)...); + else + static_assert(is_constructible_v<_Smart, _Sp, _Args...>); + }; + + if constexpr (sizeof...(_Args) >= 2) + std::apply(__reset, std::move(_M_args)); + else if constexpr (sizeof...(_Args) == 1) + __reset(std::get<0>(std::move(_M_args))); + else + __reset(); + } + /// @endcond + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // __glibcxx_out_ptr +#endif /* _GLIBCXX_OUT_PTR_H */ diff --git a/template/sysroot/include/bits/parse_numbers.h b/template/sysroot/include/bits/parse_numbers.h new file mode 100644 index 0000000..97c08ca --- /dev/null +++ b/template/sysroot/include/bits/parse_numbers.h @@ -0,0 +1,295 @@ +// Components for compile-time parsing of numbers -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/parse_numbers.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{chrono} + */ + +#ifndef _GLIBCXX_PARSE_NUMBERS_H +#define _GLIBCXX_PARSE_NUMBERS_H 1 + +#pragma GCC system_header + +// From n3642.pdf except I added binary literals and digit separator '\''. + +#if __cplusplus >= 201402L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __parse_int +{ + template + struct _Digit; + + template + struct _Digit<_Base, '0'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit<_Base, '1'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit_impl : integral_constant + { + static_assert(_Base > _Val, "invalid digit"); + using __valid = true_type; + }; + + template + struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2> + { }; + + template + struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3> + { }; + + template + struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4> + { }; + + template + struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5> + { }; + + template + struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6> + { }; + + template + struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7> + { }; + + template + struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8> + { }; + + template + struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9> + { }; + + template + struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf> + { }; + + template + struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf> + { }; + + // Digit separator + template + struct _Digit<_Base, '\''> : integral_constant + { + using __valid = false_type; + }; + +//------------------------------------------------------------------------------ + + template + using __ull_constant = integral_constant; + + template + struct _Power_help + { + using __next = typename _Power_help<_Base, _Digs...>::type; + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type + = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>; + }; + + template + struct _Power_help<_Base, _Dig> + { + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type = __ull_constant<__valid_digit::value>; + }; + + template + struct _Power : _Power_help<_Base, _Digs...>::type + { }; + + template + struct _Power<_Base> : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Number_help + { + using __digit = _Digit<_Base, _Dig>; + using __valid_digit = typename __digit::__valid; + using __next = _Number_help<_Base, + __valid_digit::value ? _Pow / _Base : _Pow, + _Digs...>; + using type = __ull_constant<_Pow * __digit::value + __next::type::value>; + static_assert((type::value / _Pow) == __digit::value, + "integer literal does not fit in unsigned long long"); + }; + + // Skip past digit separators: + template + struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...> + : _Number_help<_Base, _Pow, _Dig, _Digs...> + { }; + + // Terminating case for recursion: + template + struct _Number_help<_Base, 1ULL, _Dig> + { + using type = __ull_constant<_Digit<_Base, _Dig>::value>; + }; + + template + struct _Number + : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type + { }; + + template + struct _Number<_Base> + : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Parse_int; + + template + struct _Parse_int<'0', 'b', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'B', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'x', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'X', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', _Digs...> + : _Number<8U, _Digs...>::type + { }; + + template + struct _Parse_int + : _Number<10U, _Digs...>::type + { }; + +} // namespace __parse_int + + +namespace __select_int +{ + template + struct _Select_int_base; + + template + struct _Select_int_base<_Val, _IntType, _Ints...> + : __conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max), + integral_constant<_IntType, (_IntType)_Val>, + _Select_int_base<_Val, _Ints...>> + { }; + + template + struct _Select_int_base<_Val> + { }; + + template + using _Select_int = typename _Select_int_base< + __parse_int::_Parse_int<_Digs...>::value, + unsigned char, + unsigned short, + unsigned int, + unsigned long, + unsigned long long + >::type; + +} // namespace __select_int + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_PARSE_NUMBERS_H diff --git a/template/sysroot/include/bits/predefined_ops.h b/template/sysroot/include/bits/predefined_ops.h new file mode 100644 index 0000000..f72d511 --- /dev/null +++ b/template/sysroot/include/bits/predefined_ops.h @@ -0,0 +1,407 @@ +// Default predicates for internal use -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file predefined_ops.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_PREDEFINED_OPS_H +#define _GLIBCXX_PREDEFINED_OPS_H 1 + +#include + +namespace __gnu_cxx +{ +namespace __ops +{ + struct _Iter_less_iter + { + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 < *__it2; } + }; + + _GLIBCXX14_CONSTEXPR + inline _Iter_less_iter + __iter_less_iter() + { return _Iter_less_iter(); } + + struct _Iter_less_val + { +#if __cplusplus >= 201103L + constexpr _Iter_less_val() = default; +#else + _Iter_less_val() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_less_val(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it < __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_less_val() + { return _Iter_less_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_comp_val(_Iter_less_iter) + { return _Iter_less_val(); } + + struct _Val_less_iter + { +#if __cplusplus >= 201103L + constexpr _Val_less_iter() = default; +#else + _Val_less_iter() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Val_less_iter(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) const + { return __val < *__it; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_less_iter() + { return _Val_less_iter(); } + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_comp_iter(_Iter_less_iter) + { return _Val_less_iter(); } + + struct _Iter_equal_to_iter + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 == *__it2; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_iter + __iter_equal_to_iter() + { return _Iter_equal_to_iter(); } + + struct _Iter_equal_to_val + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it == __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_equal_to_val() + { return _Iter_equal_to_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_comp_val(_Iter_equal_to_iter) + { return _Iter_equal_to_val(); } + + template + struct _Iter_comp_iter + { + _Compare _M_comp; + + explicit _GLIBCXX14_CONSTEXPR + _Iter_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) + { return bool(_M_comp(*__it1, *__it2)); } + }; + + template + _GLIBCXX14_CONSTEXPR + inline _Iter_comp_iter<_Compare> + __iter_comp_iter(_Compare __comp) + { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_comp_val + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) + { return bool(_M_comp(*__it, __val)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Compare __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Iter_comp_iter<_Compare> __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Val_comp_iter + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) + { return bool(_M_comp(__val, *__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Compare __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Iter_comp_iter<_Compare> __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_equals_val + { + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_val(_Value& __value) + : _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return *__it == _M_value; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_val<_Value> + __iter_equals_val(_Value& __val) + { return _Iter_equals_val<_Value>(__val); } + + template + struct _Iter_equals_iter + { + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_iter(_Iterator1 __it1) + : _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return *__it2 == *_M_it1; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_iter<_Iterator> + __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it) + { return _Iter_equals_iter<_Iterator>(__it); } + + template + struct _Iter_pred + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_pred(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_pred<_Predicate> + __pred_iter(_Predicate __pred) + { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } + + template + struct _Iter_comp_to_val + { + _Compare _M_comp; + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_val(_Compare __comp, _Value& __value) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_comp(*__it, _M_value)); } + }; + + template + _Iter_comp_to_val<_Compare, _Value> + _GLIBCXX20_CONSTEXPR + __iter_comp_val(_Compare __comp, _Value &__val) + { + return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); + } + + template + struct _Iter_comp_to_iter + { + _Compare _M_comp; + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return bool(_M_comp(*__it2, *_M_it1)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_to_iter<_Compare, _Iterator> + __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) + { + return _Iter_comp_to_iter<_Compare, _Iterator>( + _GLIBCXX_MOVE(__comp._M_comp), __it); + } + + template + struct _Iter_negate + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_negate(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return !bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_negate<_Predicate> + __negate(_Iter_pred<_Predicate> __pred) + { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } + +} // namespace __ops +} // namespace __gnu_cxx + +#endif diff --git a/template/sysroot/include/bits/ptr_traits.h b/template/sysroot/include/bits/ptr_traits.h new file mode 100644 index 0000000..6c65001 --- /dev/null +++ b/template/sysroot/include/bits/ptr_traits.h @@ -0,0 +1,262 @@ +// Pointer Traits -*- C++ -*- + +// Copyright (C) 2011-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ptr_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _PTR_TRAITS_H +#define _PTR_TRAITS_H 1 + +#if __cplusplus >= 201103L + +#include + +#if __cplusplus > 201703L +#include +namespace __gnu_debug { struct _Safe_iterator_base; } +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + + class __undefined; + + // For a specialization `SomeTemplate` the member `type` is T, + // otherwise `type` is `__undefined`. + template + struct __get_first_arg + { using type = __undefined; }; + + template class _SomeTemplate, typename _Tp, + typename... _Types> + struct __get_first_arg<_SomeTemplate<_Tp, _Types...>> + { using type = _Tp; }; + + // For a specialization `SomeTemplate` and a type `U` the member + // `type` is `SomeTemplate`, otherwise there is no member `type`. + template + struct __replace_first_arg + { }; + + template class _SomeTemplate, typename _Up, + typename _Tp, typename... _Types> + struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up> + { using type = _SomeTemplate<_Up, _Types...>; }; + + // Detect the element type of a pointer-like type. + template + struct __ptr_traits_elem : __get_first_arg<_Ptr> + { }; + + // Use _Ptr::element_type if is a valid type. +#if __cpp_concepts + template requires requires { typename _Ptr::element_type; } + struct __ptr_traits_elem<_Ptr, void> + { using type = typename _Ptr::element_type; }; +#else + template + struct __ptr_traits_elem<_Ptr, __void_t> + { using type = typename _Ptr::element_type; }; +#endif + + template + using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type; + + /// @endcond + + // Define pointer_traits

    ::pointer_to. + template::value> + struct __ptr_traits_ptr_to + { + using pointer = _Ptr; + using element_type = _Elt; + + /** + * @brief Obtain a pointer to an object + * @param __r A reference to an object of type `element_type` + * @return `pointer::pointer_to(__r)` + * @pre `pointer::pointer_to(__r)` is a valid expression. + */ + static pointer + pointer_to(element_type& __r) +#if __cpp_lib_concepts + requires requires { + { pointer::pointer_to(__r) } -> convertible_to; + } +#endif + { return pointer::pointer_to(__r); } + }; + + // Do not define pointer_traits

    WLsuT7R2i)M&J{B`njEb3! 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 dgvDXTJML6C*0?(HUTH} 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 Bh#3F? literal 0 HcmV?d00001 diff --git a/template/sysroot/lib/libjpeg.a b/template/sysroot/lib/libjpeg.a new file mode 100644 index 0000000000000000000000000000000000000000..38bca665766d9a5fbbe29f6e86b84688a8ce5e49 GIT binary patch literal 330158 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

    j-a|tq)$3vf8bPP-a_eTy@F9yK)MXa8 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 ko)EGU>XZJO$^ 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 JRU2FW{XfXGUZ(&6 literal 0 HcmV?d00001

    ::pointer_to if element type is void. + template + struct __ptr_traits_ptr_to<_Ptr, _Elt, true> + { }; + + // Partial specialization defining pointer_traits::pointer_to(T&). + template + struct __ptr_traits_ptr_to<_Tp*, _Tp, false> + { + using pointer = _Tp*; + using element_type = _Tp; + + /** + * @brief Obtain a pointer to an object + * @param __r A reference to an object of type `element_type` + * @return `addressof(__r)` + */ + static _GLIBCXX20_CONSTEXPR pointer + pointer_to(element_type& __r) noexcept + { return std::addressof(__r); } + }; + + template + struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt> + { + private: + template + using __diff_t = typename _Tp::difference_type; + + template + using __rebind = __type_identity>; + + public: + /// The pointer type. + using pointer = _Ptr; + + /// The type pointed to. + using element_type = _Elt; + + /// The type used to represent the difference between two pointers. + using difference_type = __detected_or_t; + + /// A pointer to a different type. + template + using rebind = typename __detected_or_t<__replace_first_arg<_Ptr, _Up>, + __rebind, _Ptr, _Up>::type; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3545. std::pointer_traits should be SFINAE-friendly + template + struct __ptr_traits_impl<_Ptr, __undefined> + { }; + + /** + * @brief Uniform interface to all pointer-like types + * @headerfile memory + * @ingroup pointer_abstractions + * @since C++11 + */ + template + struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>> + { }; + + /** + * @brief Partial specialization for built-in pointers. + * @headerfile memory + * @ingroup pointer_abstractions + * @since C++11 + */ + template + struct pointer_traits<_Tp*> : __ptr_traits_ptr_to<_Tp*, _Tp> + { + /// The pointer type + typedef _Tp* pointer; + /// The type pointed to + typedef _Tp element_type; + /// Type used to represent the difference between two pointers + typedef ptrdiff_t difference_type; + /// A pointer to a different type. + template using rebind = _Up*; + }; + + /// Convenience alias for rebinding pointers. + template + using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; + + template + constexpr _Tp* + __to_address(_Tp* __ptr) noexcept + { + static_assert(!std::is_function<_Tp>::value, "not a function pointer"); + return __ptr; + } + +#ifndef __glibcxx_to_address // C++ < 20 + template + constexpr typename std::pointer_traits<_Ptr>::element_type* + __to_address(const _Ptr& __ptr) + { return std::__to_address(__ptr.operator->()); } +#else + template + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) + { return std::pointer_traits<_Ptr>::to_address(__ptr); } + + template + constexpr auto + __to_address(const _Ptr& __ptr, _None...) noexcept + { + if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) + return std::__to_address(__ptr.base().operator->()); + else + return std::__to_address(__ptr.operator->()); + } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c __ptr + * @ingroup pointer_abstractions + */ + template + constexpr _Tp* + to_address(_Tp* __ptr) noexcept + { return std::__to_address(__ptr); } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is + well-formed, otherwise @c to_address(__ptr.operator->()) + * @ingroup pointer_abstractions + */ + template + constexpr auto + to_address(const _Ptr& __ptr) noexcept + { return std::__to_address(__ptr); } +#endif // __glibcxx_to_address + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif + +#endif diff --git a/template/sysroot/include/bits/range_access.h b/template/sysroot/include/bits/range_access.h new file mode 100644 index 0000000..a9896d1 --- /dev/null +++ b/template/sysroot/include/bits/range_access.h @@ -0,0 +1,370 @@ +// Range access functions for containers -*- C++ -*- + +// Copyright (C) 2010-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/range_access.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _GLIBCXX_RANGE_ACCESS_H +#define _GLIBCXX_RANGE_ACCESS_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +#include +#include // common_type_t, make_signed_t +#include // reverse_iterator + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Return an iterator pointing to the first element of + * the container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + begin(_Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + begin(const _Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + end(_Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + end(const _Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to the first element of the array. + * @param __arr Array. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX14_CONSTEXPR _Tp* + begin(_Tp (&__arr)[_Nm]) noexcept + { return __arr; } + + /** + * @brief Return an iterator pointing to one past the last element + * of the array. + * @param __arr Array. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX14_CONSTEXPR _Tp* + end(_Tp (&__arr)[_Nm]) noexcept + { return __arr + _Nm; } + +#if __cplusplus >= 201402L + + template class valarray; + // These overloads must be declared for cbegin and cend to use them. + template _Tp* begin(valarray<_Tp>&) noexcept; + template const _Tp* begin(const valarray<_Tp>&) noexcept; + template _Tp* end(valarray<_Tp>&) noexcept; + template const _Tp* end(const valarray<_Tp>&) noexcept; + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + constexpr auto + cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont))) + -> decltype(std::begin(__cont)) + { return std::begin(__cont); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + constexpr auto + cend(const _Container& __cont) noexcept(noexcept(std::end(__cont))) + -> decltype(std::end(__cont)) + { return std::end(__cont); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + rbegin(_Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + rbegin(const _Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + rend(_Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + rend(const _Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the array. + * @param __arr Array. + */ + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rbegin(_Tp (&__arr)[_Nm]) noexcept + { return reverse_iterator<_Tp*>(__arr + _Nm); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the array. + * @param __arr Array. + */ + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rend(_Tp (&__arr)[_Nm]) noexcept + { return reverse_iterator<_Tp*>(__arr); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the initializer_list. + * @param __il initializer_list. + */ + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin(initializer_list<_Tp> __il) noexcept + { return reverse_iterator(__il.end()); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the initializer_list. + * @param __il initializer_list. + */ + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rend(initializer_list<_Tp> __il) noexcept + { return reverse_iterator(__il.begin()); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont)) + { return std::rbegin(__cont); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + [[__nodiscard__, __gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR auto + crend(const _Container& __cont) -> decltype(std::rend(__cont)) + { return std::rend(__cont); } + +#endif // C++14 + +#ifdef __glibcxx_nonmember_container_access // C++ >= 17 + /** + * @brief Return the size of a container. + * @param __cont Container. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr auto + size(const _Container& __cont) noexcept(noexcept(__cont.size())) + -> decltype(__cont.size()) + { return __cont.size(); } + + /** + * @brief Return the size of an array. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr size_t + size(const _Tp (&)[_Nm]) noexcept + { return _Nm; } + + /** + * @brief Return whether a container is empty. + * @param __cont Container. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr auto + empty(const _Container& __cont) noexcept(noexcept(__cont.empty())) + -> decltype(__cont.empty()) + { return __cont.empty(); } + + /** + * @brief Return whether an array is empty (always false). + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr bool + empty(const _Tp (&)[_Nm]) noexcept + { return false; } + + /** + * @brief Return whether an initializer_list is empty. + * @param __il Initializer list. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr bool + empty(initializer_list<_Tp> __il) noexcept + { return __il.size() == 0;} + + /** + * @brief Return the data pointer of a container. + * @param __cont Container. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr auto + data(_Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of a const container. + * @param __cont Container. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr auto + data(const _Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of an array. + * @param __array Array. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr _Tp* + data(_Tp (&__array)[_Nm]) noexcept + { return __array; } + + /** + * @brief Return the data pointer of an initializer list. + * @param __il Initializer list. + */ + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr const _Tp* + data(initializer_list<_Tp> __il) noexcept + { return __il.begin(); } +#endif // __glibcxx_nonmember_container_access + +#ifdef __glibcxx_ssize // C++ >= 20 + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr auto + ssize(const _Container& __cont) + noexcept(noexcept(__cont.size())) + -> common_type_t> + { + using type = make_signed_t; + return static_cast>(__cont.size()); + } + + template + [[nodiscard, __gnu__::__always_inline__]] + constexpr ptrdiff_t + ssize(const _Tp (&)[_Num]) noexcept + { return _Num; } +#endif // __glibcxx_ssize +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 +#endif // _GLIBCXX_RANGE_ACCESS_H diff --git a/template/sysroot/include/bits/ranges_algo.h b/template/sysroot/include/bits/ranges_algo.h new file mode 100644 index 0000000..62faff1 --- /dev/null +++ b/template/sysroot/include/bits/ranges_algo.h @@ -0,0 +1,4051 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGO_H +#define _RANGES_ALGO_H 1 + +#if __cplusplus > 201703L + +#if __cplusplus > 202002L +#include +#endif +#include +#include +#include // concept uniform_random_bit_generator + +#if __glibcxx_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr auto + __make_comp_proj(_Comp& __comp, _Proj& __proj) + { + return [&] (auto&& __lhs, auto&& __rhs) -> bool { + using _TL = decltype(__lhs); + using _TR = decltype(__rhs); + return std::__invoke(__comp, + std::__invoke(__proj, std::forward<_TL>(__lhs)), + std::__invoke(__proj, std::forward<_TR>(__rhs))); + }; + } + + template + constexpr auto + __make_pred_proj(_Pred& __pred, _Proj& __proj) + { + return [&] (_Tp&& __arg) -> bool { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_Tp>(__arg))); + }; + } + } // namespace __detail + + struct __all_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __all_of_fn all_of{}; + + struct __any_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return true; + return false; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __any_of_fn any_of{}; + + struct __none_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __none_of_fn none_of{}; + + template + struct in_fun_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Fp fun; + + template + requires convertible_to + && convertible_to + constexpr + operator in_fun_result<_Iter2, _F2p>() const & + { return {in, fun}; } + + template + requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> + constexpr + operator in_fun_result<_Iter2, _F2p>() && + { return {std::move(in), std::move(fun)}; } + }; + + template + using for_each_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_fn + { + template _Sent, + typename _Proj = identity, + indirectly_unary_invocable> _Fun> + constexpr for_each_result<_Iter, _Fun> + operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + std::__invoke(__f, std::__invoke(__proj, *__first)); + return { std::move(__first), std::move(__f) }; + } + + template, _Proj>> + _Fun> + constexpr for_each_result, _Fun> + operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__f), std::move(__proj)); + } + }; + + inline constexpr __for_each_fn for_each{}; + + template + using for_each_n_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_n_fn + { + template> _Fun> + constexpr for_each_n_result<_Iter, _Fun> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Fun __f, _Proj __proj = {}) const + { + if constexpr (random_access_iterator<_Iter>) + { + if (__n <= 0) + return {std::move(__first), std::move(__f)}; + auto __last = __first + __n; + return ranges::for_each(std::move(__first), std::move(__last), + std::move(__f), std::move(__proj)); + } + else + { + while (__n-- > 0) + { + std::__invoke(__f, std::__invoke(__proj, *__first)); + ++__first; + } + return {std::move(__first), std::move(__f)}; + } + } + }; + + inline constexpr __for_each_n_fn for_each_n{}; + + // find, find_if and find_if_not are defined in . + + struct __find_first_of_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr _Iter1 + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1; ++__first1) + for (auto __iter = __first2; __iter != __last2; ++__iter) + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__iter))) + return __first1; + return __first1; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_iterator_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_first_of_fn find_first_of{}; + + struct __count_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + ++__n; + return __n; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __count_fn count{}; + + struct __count_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__n; + return __n; + } + + template, _Proj>> + _Pred> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __count_if_fn count_if{}; + + // in_in_result, mismatch and search are defined in . + + struct __search_n_fn + { + template _Sent, typename _Tp, + typename _Pred = ranges::equal_to, typename _Proj = identity> + requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + if (__count <= 0) + return {__first, __first}; + + auto __value_comp = [&] (_Rp&& __arg) -> bool { + return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); + }; + if (__count == 1) + { + __first = ranges::find_if(std::move(__first), __last, + std::move(__value_comp), + std::move(__proj)); + if (__first == __last) + return {__first, __first}; + else + { + auto __end = __first; + return {__first, ++__end}; + } + } + + if constexpr (sized_sentinel_for<_Sent, _Iter> + && random_access_iterator<_Iter>) + { + auto __tail_size = __last - __first; + auto __remainder = __count; + + while (__remainder <= __tail_size) + { + __first += __remainder; + __tail_size -= __remainder; + auto __backtrack = __first; + while (__value_comp(std::__invoke(__proj, *--__backtrack))) + { + if (--__remainder == 0) + return {__first - __count, __first}; + } + __remainder = __count + 1 - (__first - __backtrack); + } + auto __i = __first + __tail_size; + return {__i, __i}; + } + else + { + __first = ranges::find_if(__first, __last, __value_comp, __proj); + while (__first != __last) + { + auto __n = __count; + auto __i = __first; + ++__i; + while (__i != __last && __n != 1 + && __value_comp(std::__invoke(__proj, *__i))) + { + ++__i; + --__n; + } + if (__n == 1) + return {__first, __i}; + if (__i == __last) + return {__i, __i}; + __first = ranges::find_if(++__i, __last, __value_comp, __proj); + } + return {__first, __first}; + } + } + + template + requires indirectly_comparable, const _Tp*, + _Pred, _Proj> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__count), __value, + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __search_n_fn search_n{}; + + struct __find_end_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (bidirectional_iterator<_Iter1> + && bidirectional_iterator<_Iter2>) + { + auto __i1 = ranges::next(__first1, __last1); + auto __i2 = ranges::next(__first2, __last2); + auto __rresult + = ranges::search(reverse_iterator<_Iter1>{__i1}, + reverse_iterator<_Iter1>{__first1}, + reverse_iterator<_Iter2>{__i2}, + reverse_iterator<_Iter2>{__first2}, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + auto __result_first = ranges::end(__rresult).base(); + auto __result_last = ranges::begin(__rresult).base(); + if (__result_last == __first1) + return {__i1, __i1}; + else + return {__result_first, __result_last}; + } + else + { + auto __i = ranges::next(__first1, __last1); + if (__first2 == __last2) + return {__i, __i}; + + auto __result_begin = __i; + auto __result_end = __i; + for (;;) + { + auto __new_range = ranges::search(__first1, __last1, + __first2, __last2, + __pred, __proj1, __proj2); + auto __new_result_begin = ranges::begin(__new_range); + auto __new_result_end = ranges::end(__new_range); + if (__new_result_begin == __last1) + return {__result_begin, __result_end}; + else + { + __result_begin = __new_result_begin; + __result_end = __new_result_end; + __first1 = __result_begin; + ++__first1; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_end_fn find_end{}; + + // adjacent_find is defined in . + + struct __is_permutation_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred + = ranges::equal_to> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + + if constexpr (__sized_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + auto&& __proj_scan = std::__invoke(__proj1, *__scan); + auto __comp_scan = [&] (_Tp&& __arg) -> bool { + return std::__invoke(__pred, __proj_scan, + std::forward<_Tp>(__arg)); + }; + if (__scan != ranges::find_if(__first1, __scan, + __comp_scan, __proj1)) + continue; // We've seen this one before. + + auto __matches = ranges::count_if(__first2, __last2, + __comp_scan, __proj2); + if (__matches == 0 + || ranges::count_if(__scan, __last1, + __comp_scan, __proj1) != __matches) + return false; + } + return true; + } + + template, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __is_permutation_fn is_permutation{}; + + template + using copy_if_result = in_out_result<_Iter, _Out>; + + struct __copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __copy_if_fn copy_if{}; + + template + using swap_ranges_result = in_in_result<_Iter1, _Iter2>; + + struct __swap_ranges_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> + requires indirectly_swappable<_Iter1, _Iter2> + constexpr swap_ranges_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + ranges::iter_swap(__first1, __first2); + return {std::move(__first1), std::move(__first2)}; + } + + template + requires indirectly_swappable, iterator_t<_Range2>> + constexpr swap_ranges_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } + }; + + inline constexpr __swap_ranges_fn swap_ranges{}; + + template + using unary_transform_result = in_out_result<_Iter, _Out>; + + template + struct in_in_out_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() const & + { return {in1, in2, out}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + && convertible_to<_Out, _OOut> + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() && + { return {std::move(in1), std::move(in2), std::move(out)}; } + }; + + template + using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __transform_fn + { + template _Sent, + weakly_incrementable _Out, + copy_constructible _Fp, typename _Proj = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter, _Proj>>> + constexpr unary_transform_result<_Iter, _Out> + operator()(_Iter __first1, _Sent __last1, _Out __result, + _Fp __op, _Proj __proj = {}) const + { + for (; __first1 != __last1; ++__first1, (void)++__result) + *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); + return {std::move(__first1), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj>>> + constexpr unary_transform_result, _Out> + operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__op), std::move(__proj)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, copy_constructible _Fp, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>>> + constexpr binary_transform_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2, ++__result) + *__result = std::__invoke(__binary_op, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2)); + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj1>, + projected, _Proj2>>> + constexpr binary_transform_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__binary_op), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __transform_fn transform{}; + + struct __replace_fn + { + template _Sent, + typename _Tp1, typename _Tp2, typename _Proj = identity> + requires indirectly_writable<_Iter, const _Tp2&> + && indirect_binary_predicate, + const _Tp1*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __old_value) + *__first = __new_value; + return __first; + } + + template + requires indirectly_writable, const _Tp2&> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __old_value, __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_fn replace{}; + + struct __replace_if_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_writable<_Iter, const _Tp&> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__first = __new_value; + return std::move(__first); + } + + template, _Proj>> + _Pred> + requires indirectly_writable, const _Tp&> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_if_fn replace_if{}; + + template + using replace_copy_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_fn + { + template _Sent, + typename _Tp1, typename _Tp2, output_iterator _Out, + typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, const _Tp1*> + constexpr replace_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__proj, *__first) == __old_value) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, typename _Proj = identity> + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr replace_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __old_value, + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_fn replace_copy{}; + + template + using replace_copy_if_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_if_fn + { + template _Sent, + typename _Tp, output_iterator _Out, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr replace_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, + typename _Proj = identity, + indirect_unary_predicate, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr replace_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__pred), + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_if_fn replace_copy_if{}; + + struct __generate_n_fn + { + template + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const + { + for (; __n > 0; --__n, (void)++__first) + *__first = std::__invoke(__gen); + return __first; + } + }; + + inline constexpr __generate_n_fn generate_n{}; + + struct __generate_fn + { + template _Sent, + copy_constructible _Fp> + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, _Sent __last, _Fp __gen) const + { + for (; __first != __last; ++__first) + *__first = std::__invoke(__gen); + return __first; + } + + template + requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Fp __gen) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__gen)); + } + }; + + inline constexpr __generate_fn generate{}; + + struct __remove_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if(__first, __last, __pred, __proj); + if (__first == __last) + return {__first, __first}; + + auto __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = std::move(*__first); + ++__result; + } + + return {__result, __first}; + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_if_fn remove_if{}; + + struct __remove_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + auto __pred = [&] (auto&& __arg) -> bool { + return std::forward(__arg) == __value; + }; + return ranges::remove_if(__first, __last, + std::move(__pred), std::move(__proj)); + } + + template + requires permutable> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __remove_fn remove{}; + + template + using remove_copy_if_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr remove_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr remove_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_copy_if_fn remove_copy_if{}; + + template + using remove_copy_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, + const _Tp*> + constexpr remove_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(std::__invoke(__proj, *__first) == __value)) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr remove_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __value, std::move(__proj)); + } + }; + + inline constexpr __remove_copy_fn remove_copy{}; + + struct __unique_fn + { + template _Sent, + typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + __first = ranges::adjacent_find(__first, __last, __comp, __proj); + if (__first == __last) + return {__first, __first}; + + auto __dest = __first; + ++__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__dest), + std::__invoke(__proj, *__first))) + *++__dest = std::move(*__first); + return {++__dest, __first}; + } + + template, _Proj>> _Comp = ranges::equal_to> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_fn unique{}; + + namespace __detail + { + template + concept __can_reread_output = input_iterator<_Out> + && same_as<_Tp, iter_value_t<_Out>>; + } + + template + using unique_copy_result = in_out_result<_Iter, _Out>; + + struct __unique_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable<_Iter, _Out> + && (forward_iterator<_Iter> + || __detail::__can_reread_output<_Out, iter_value_t<_Iter>> + || indirectly_copyable_storable<_Iter, _Out>) + constexpr unique_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), std::move(__result)}; + + // TODO: perform a closer comparison with reference implementations + if constexpr (forward_iterator<_Iter>) + { + auto __next = __first; + *__result = *__next; + while (++__next != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + { + __first = __next; + *++__result = *__first; + } + return {__next, std::move(++__result)}; + } + else if constexpr (__detail::__can_reread_output<_Out, iter_value_t<_Iter>>) + { + *__result = *__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__result), + std::__invoke(__proj, *__first))) + *++__result = *__first; + return {std::move(__first), std::move(++__result)}; + } + else // indirectly_copyable_storable<_Iter, _Out> + { + auto __value = *__first; + *__result = __value; + while (++__first != __last) + { + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, __value))) + { + __value = *__first; + *++__result = __value; + } + } + return {std::move(__first), std::move(++__result)}; + } + } + + template, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _Out> + && (forward_iterator> + || __detail::__can_reread_output<_Out, range_value_t<_Range>> + || indirectly_copyable_storable, _Out>) + constexpr unique_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_copy_fn unique_copy{}; + + struct __reverse_fn + { + template _Sent> + requires permutable<_Iter> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + + if constexpr (random_access_iterator<_Iter>) + { + if (__first != __last) + { + --__tail; + while (__first < __tail) + { + ranges::iter_swap(__first, __tail); + ++__first; + --__tail; + } + } + return __i; + } + else + { + for (;;) + if (__first == __tail || __first == --__tail) + break; + else + { + ranges::iter_swap(__first, __tail); + ++__first; + } + return __i; + } + } + + template + requires permutable> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __reverse_fn reverse{}; + + template + using reverse_copy_result = in_out_result<_Iter, _Out>; + + struct __reverse_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr reverse_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + while (__first != __tail) + { + --__tail; + *__result = *__tail; + ++__result; + } + return {__i, std::move(__result)}; + } + + template + requires indirectly_copyable, _Out> + constexpr reverse_copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __reverse_copy_fn reverse_copy{}; + + struct __rotate_fn + { + template _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Iter __middle, _Sent __last) const + { + auto __lasti = ranges::next(__first, __last); + if (__first == __middle) + return {__lasti, __lasti}; + if (__last == __middle) + return {std::move(__first), std::move(__lasti)}; + + if constexpr (random_access_iterator<_Iter>) + { + auto __n = __lasti - __first; + auto __k = __middle - __first; + + if (__k == __n - __k) + { + ranges::swap_ranges(__first, __middle, __middle, __middle + __k); + return {std::move(__middle), std::move(__lasti)}; + } + + auto __p = __first; + auto __ret = __first + (__lasti - __middle); + + for (;;) + { + if (__k < __n - __k) + { + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*__p); + ranges::move(__p + 1, __p + __n, __p); + *(__p + __n - 1) = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + ranges::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + ranges::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*(__p + __n - 1)); + ranges::move_backward(__p, __p + __n - 1, __p + __n); + *__p = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __n; + __p = __q - __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + ranges::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + std::swap(__n, __k); + } + } + } + else if constexpr (bidirectional_iterator<_Iter>) + { + auto __tail = __lasti; + + ranges::reverse(__first, __middle); + ranges::reverse(__middle, __tail); + + while (__first != __middle && __middle != __tail) + { + ranges::iter_swap(__first, --__tail); + ++__first; + } + + if (__first == __middle) + { + ranges::reverse(__middle, __tail); + return {std::move(__tail), std::move(__lasti)}; + } + else + { + ranges::reverse(__first, __middle); + return {std::move(__first), std::move(__lasti)}; + } + } + else + { + auto __first2 = __middle; + do + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + auto __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return {std::move(__ret), std::move(__lasti)}; + } + } + + template + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r)); + } + }; + + inline constexpr __rotate_fn rotate{}; + + template + using rotate_copy_result = in_out_result<_Iter, _Out>; + + struct __rotate_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr rotate_copy_result<_Iter, _Out> + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Out __result) const + { + auto __copy1 = ranges::copy(__middle, + std::move(__last), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first), + std::move(__middle), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.out) }; + } + + template + requires indirectly_copyable, _Out> + constexpr rotate_copy_result, _Out> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), std::move(__result)); + } + }; + + inline constexpr __rotate_copy_fn rotate_copy{}; + + struct __sample_fn + { + template _Sent, + weakly_incrementable _Out, typename _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_Out>) + && indirectly_copyable<_Iter, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Iter __first, _Sent __last, _Out __out, + iter_difference_t<_Iter> __n, _Gen&& __g) const + { + if constexpr (forward_iterator<_Iter>) + { + // FIXME: Forwarding to std::sample here requires computing __lasti + // which may take linear time. + auto __lasti = ranges::next(__first, __last); + return _GLIBCXX_STD_A:: + sample(std::move(__first), std::move(__lasti), std::move(__out), + __n, std::forward<_Gen>(__g)); + } + else + { + using __distrib_type + = uniform_int_distribution>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + iter_difference_t<_Iter> __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + } + + template + requires (forward_range<_Range> || random_access_iterator<_Out>) + && indirectly_copyable, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Range&& __r, _Out __out, + range_difference_t<_Range> __n, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__out), __n, + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __sample_fn sample{}; + + struct __shuffle_fn + { + template _Sent, + typename _Gen> + requires permutable<_Iter> + && uniform_random_bit_generator> + _Iter + operator()(_Iter __first, _Sent __last, _Gen&& __g) const + { + auto __lasti = ranges::next(__first, __last); + std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); + return __lasti; + } + + template + requires permutable> + && uniform_random_bit_generator> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __shuffle_fn shuffle{}; + + struct __push_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::push_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __push_heap_fn push_heap{}; + + struct __pop_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::pop_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __pop_heap_fn pop_heap{}; + + struct __make_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::make_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __make_heap_fn make_heap{}; + + struct __sort_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_heap_fn sort_heap{}; + + struct __is_heap_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = ranges::distance(__first, __last); + iter_difference_t<_Iter> __parent = 0, __child = 1; + for (; __child < __n; ++__child) + if (std::__invoke(__comp, + std::__invoke(__proj, *(__first + __parent)), + std::__invoke(__proj, *(__first + __child)))) + return __first + __child; + else if ((__child & 1) == 0) + ++__parent; + + return __first + __n; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_until_fn is_heap_until{}; + + struct __is_heap_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (__last + == ranges::is_heap_until(__first, __last, + std::move(__comp), + std::move(__proj))); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_fn is_heap{}; + + struct __sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + _GLIBCXX_STD_A::sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_fn sort{}; + + struct __stable_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::stable_sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __stable_sort_fn stable_sort{}; + + struct __partial_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __middle) + return ranges::next(__first, __last); + + ranges::make_heap(__first, __middle, __comp, __proj); + auto __i = __middle; + for (; __i != __last; ++__i) + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + { + ranges::pop_heap(__first, __middle, __comp, __proj); + ranges::iter_swap(__middle-1, __i); + ranges::push_heap(__first, __middle, __comp, __proj); + } + ranges::sort_heap(__first, __middle, __comp, __proj); + + return __i; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __partial_sort_fn partial_sort{}; + + template + using partial_sort_copy_result = in_out_result<_Iter, _Out>; + + struct __partial_sort_copy_fn + { + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> + && sortable<_Iter2, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>> + constexpr partial_sort_copy_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, + _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__result_first == __result_last) + { + // TODO: Eliminating the variable __lasti triggers an ICE. + auto __lasti = ranges::next(std::move(__first), + std::move(__last)); + return {std::move(__lasti), std::move(__result_first)}; + } + + auto __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); + for (; __first != __last; ++__first) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first), + std::__invoke(__proj2, *__result_first))) + { + ranges::pop_heap(__result_first, __result_real_last, + __comp, __proj2); + *(__result_real_last-1) = *__first; + ranges::push_heap(__result_first, __result_real_last, + __comp, __proj2); + } + ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); + + return {std::move(__first), std::move(__result_real_last)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> + && sortable, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + constexpr partial_sort_copy_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + ranges::begin(__out), ranges::end(__out), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __partial_sort_copy_fn partial_sort_copy{}; + + struct __is_sorted_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return __next; + return __next; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_until_fn is_sorted_until{}; + + struct __is_sorted_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return true; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_fn is_sorted{}; + + struct __nth_element_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + _GLIBCXX_STD_A::nth_element(std::move(__first), std::move(__nth), + __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__nth), + ranges::end(__r), std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __nth_element_fn nth_element{}; + + struct __lower_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __lower_bound_fn lower_bound{}; + + struct __upper_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __upper_bound_fn upper_bound{}; + + struct __equal_range_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, + std::__invoke(__proj, *__middle), + __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (std::__invoke(__comp, + __value, + std::__invoke(__proj, *__middle))) + __len = __half; + else + { + auto __left + = ranges::lower_bound(__first, __middle, + __value, __comp, __proj); + ranges::advance(__first, __len); + auto __right + = ranges::upper_bound(++__middle, __first, + __value, __comp, __proj); + return {__left, __right}; + } + } + return {__first, __first}; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __equal_range_fn equal_range{}; + + struct __binary_search_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); + if (__i == __last) + return false; + return !(bool)std::__invoke(__comp, __value, + std::__invoke(__proj, *__i)); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __binary_search_fn binary_search{}; + + struct __is_partitioned_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if_not(std::move(__first), __last, + __pred, __proj); + if (__first == __last) + return true; + ++__first; + return ranges::none_of(std::move(__first), std::move(__last), + std::move(__pred), std::move(__proj)); + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __is_partitioned_fn is_partitioned{}; + + struct __partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + if constexpr (bidirectional_iterator<_Iter>) + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + for (;;) + { + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (std::__invoke(__pred, + std::__invoke(__proj, *__first))) + ++__first; + else + break; + --__tail; + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (!(bool)std::__invoke(__pred, + std::__invoke(__proj, *__tail))) + --__tail; + else + break; + ranges::iter_swap(__first, __tail); + ++__first; + } + } + else + { + if (__first == __last) + return {__first, __first}; + + while (std::__invoke(__pred, std::__invoke(__proj, *__first))) + if (++__first == __last) + return {__first, __first}; + + auto __next = __first; + while (++__next != __last) + if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + { + ranges::iter_swap(__first, __next); + ++__first; + } + + return {std::move(__first), std::move(__next)}; + } + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_fn partition{}; + +#if _GLIBCXX_HOSTED + struct __stable_partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + auto __middle + = std::stable_partition(std::move(__first), __lasti, + __detail::__make_pred_proj(__pred, __proj)); + return {std::move(__middle), std::move(__lasti)}; + } + + template, _Proj>> + _Pred> + requires permutable> + borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __stable_partition_fn stable_partition{}; +#endif + + template + struct in_out_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out1 out1; + [[no_unique_address]] _Out2 out2; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() const & + { return {in, out1, out2}; } + + template + requires convertible_to<_Iter, _IIter> + && convertible_to<_Out1, _OOut1> + && convertible_to<_Out2, _OOut2> + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() && + { return {std::move(in), std::move(out1), std::move(out2)}; } + }; + + template + using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>; + + struct __partition_copy_fn + { + template _Sent, + weakly_incrementable _Out1, weakly_incrementable _Out2, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out1> + && indirectly_copyable<_Iter, _Out2> + constexpr partition_copy_result<_Iter, _Out1, _Out2> + operator()(_Iter __first, _Sent __last, + _Out1 __out_true, _Out2 __out_false, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return {std::move(__first), + std::move(__out_true), std::move(__out_false)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out1> + && indirectly_copyable, _Out2> + constexpr partition_copy_result, _Out1, _Out2> + operator()(_Range&& __r, _Out1 __out_true, _Out2 __out_false, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__out_true), std::move(__out_false), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_copy_fn partition_copy{}; + + struct __partition_point_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_point_fn partition_point{}; + + template + using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __merge_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr merge_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out) }; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr merge_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __merge_fn merge{}; + + struct __inplace_merge_fn + { + template _Sent, + typename _Comp = ranges::less, + typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::inplace_merge(std::move(__first), std::move(__middle), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __inplace_merge_fn inplace_merge{}; + + struct __includes_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + else if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __includes_fn includes{}; + + template + using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_union_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_union_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_union_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_union_fn set_union{}; + + template + using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_intersection_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_intersection_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + // TODO: Eliminating these variables triggers an ICE. + auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); + auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); + return {std::move(__last1i), std::move(__last2i), std::move(__result)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_intersection_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_intersection_fn set_intersection{}; + + template + using set_difference_result = in_out_result<_Iter, _Out>; + + struct __set_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_difference_result<_Iter1, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_difference_result, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_difference_fn set_difference{}; + + template + using set_symmetric_difference_result + = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_symmetric_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; + + // min is defined in . + + struct __max_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(__comp, + std::__invoke(__proj, __a), + std::__invoke(__proj, __b))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __result), + std::__invoke(__proj, __tmp))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_fn max{}; + + struct __clamp_fn + { + template> _Comp + = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, + _Comp __comp = {}, _Proj __proj = {}) const + { + __glibcxx_assert(!(std::__invoke(__comp, + std::__invoke(__proj, __hi), + std::__invoke(__proj, __lo)))); + auto&& __proj_val = std::__invoke(__proj, __val); + if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) + return __lo; + else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) + return __hi; + else + return __val; + } + }; + + inline constexpr __clamp_fn clamp{}; + + template + struct min_max_result + { + [[no_unique_address]] _Tp min; + [[no_unique_address]] _Tp max; + + template + requires convertible_to + constexpr + operator min_max_result<_Tp2>() const & + { return {min, max}; } + + template + requires convertible_to<_Tp, _Tp2> + constexpr + operator min_max_result<_Tp2>() && + { return {std::move(min), std::move(max)}; } + }; + + template + using minmax_result = min_max_result<_Tp>; + + struct __minmax_fn + { + template> + _Comp = ranges::less> + constexpr minmax_result + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(__comp, + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return {__b, __a}; + else + return {__a, __b}; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, range_value_t<_Range>*> + constexpr minmax_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + minmax_result> __result = {*__first, __result.min}; + if (++__first == __last) + return __result; + else + { + // At this point __result.min == __result.max, so a single + // comparison with the next element suffices. + auto&& __val = *__first; + if (__comp_proj(__val, __result.min)) + __result.min = std::forward(__val); + else + __result.max = std::forward(__val); + } + while (++__first != __last) + { + // Now process two elements at a time so that we perform at most + // 1 + 3*(N-2)/2 comparisons in total (each of the (N-2)/2 + // iterations of this loop performs three comparisons). + range_value_t<_Range> __val1 = *__first; + if (++__first == __last) + { + // N is odd; in this final iteration, we perform at most two + // comparisons, for a total of 1 + 3*(N-3)/2 + 2 comparisons, + // which is not more than 3*N/2, as required. + if (__comp_proj(__val1, __result.min)) + __result.min = std::move(__val1); + else if (!__comp_proj(__val1, __result.max)) + __result.max = std::move(__val1); + break; + } + auto&& __val2 = *__first; + if (!__comp_proj(__val2, __val1)) + { + if (__comp_proj(__val1, __result.min)) + __result.min = std::move(__val1); + if (!__comp_proj(__val2, __result.max)) + __result.max = std::forward(__val2); + } + else + { + if (__comp_proj(__val2, __result.min)) + __result.min = std::forward(__val2); + if (!__comp_proj(__val1, __result.max)) + __result.max = std::move(__val1); + } + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr minmax_result<_Tp> + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_fn minmax{}; + + struct __min_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_element_fn min_element{}; + + struct __max_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__i))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_element_fn max_element{}; + + template + using minmax_element_result = min_max_result<_Iter>; + + struct __minmax_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr minmax_element_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + minmax_element_result<_Iter> __result = {__first, __first}; + if (__first == __last || ++__first == __last) + return __result; + else + { + // At this point __result.min == __result.max, so a single + // comparison with the next element suffices. + if (__comp_proj(*__first, *__result.min)) + __result.min = __first; + else + __result.max = __first; + } + while (++__first != __last) + { + // Now process two elements at a time so that we perform at most + // 1 + 3*(N-2)/2 comparisons in total (each of the (N-2)/2 + // iterations of this loop performs three comparisons). + auto __prev = __first; + if (++__first == __last) + { + // N is odd; in this final iteration, we perform at most two + // comparisons, for a total of 1 + 3*(N-3)/2 + 2 comparisons, + // which is not more than 3*N/2, as required. + if (__comp_proj(*__prev, *__result.min)) + __result.min = __prev; + else if (!__comp_proj(*__prev, *__result.max)) + __result.max = __prev; + break; + } + if (!__comp_proj(*__first, *__prev)) + { + if (__comp_proj(*__prev, *__result.min)) + __result.min = __prev; + if (!__comp_proj(*__first, *__result.max)) + __result.max = __first; + } + else + { + if (__comp_proj(*__first, *__result.min)) + __result.min = __first; + if (!__comp_proj(*__prev, *__result.max)) + __result.max = __prev; + } + } + return __result; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr minmax_element_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_element_fn minmax_element{}; + + struct __lexicographical_compare_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + // This condition is consistent with the one in + // __lexicographical_compare_aux in . + constexpr bool __use_memcmp + = (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __ptr_to_nonvolatile<_Iter1> + && __ptr_to_nonvolatile<_Iter2> + && (is_same_v<_Comp, ranges::less> + || is_same_v<_Comp, ranges::greater>) + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + const auto __d1 = __last1 - __first1; + const auto __d2 = __last2 - __first2; + + if (const auto __len = std::min(__d1, __d2)) + { + const auto __c + = std::__memcmp(__first1, __first2, __len); + if constexpr (is_same_v<_Comp, ranges::less>) + { + if (__c < 0) + return true; + if (__c > 0) + return false; + } + else if constexpr (is_same_v<_Comp, ranges::greater>) + { + if (__c > 0) + return true; + if (__c < 0) + return false; + } + } + return __d1 < __d2; + } + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void) ++__first2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return true; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + private: + template> + static constexpr bool __ptr_to_nonvolatile + = is_pointer_v<_Iter> && !is_volatile_v>; + }; + + inline constexpr __lexicographical_compare_fn lexicographical_compare; + + template + struct in_found_result + { + [[no_unique_address]] _Iter in; + bool found; + + template + requires convertible_to + constexpr + operator in_found_result<_Iter2>() const & + { return {in, found}; } + + template + requires convertible_to<_Iter, _Iter2> + constexpr + operator in_found_result<_Iter2>() && + { return {std::move(in), found}; } + }; + + template + using next_permutation_result = in_found_result<_Iter>; + + struct __next_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__ii))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *--__j))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr next_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __next_permutation_fn next_permutation{}; + + template + using prev_permutation_result = in_found_result<_Iter>; + + struct __prev_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__ii), + std::__invoke(__proj, *__i))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *--__j), + std::__invoke(__proj, *__i))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr prev_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __prev_permutation_fn prev_permutation{}; + +#if __glibcxx_ranges_contains >= 202207L // C++ >= 23 + struct __contains_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr bool + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const + { return ranges::find(std::move(__first), __last, __value, std::move(__proj)) != __last; } + + template + requires indirect_binary_predicate, _Proj>, const _Tp*> + constexpr bool + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__proj)); } + }; + + inline constexpr __contains_fn contains{}; + + struct __contains_subrange_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return __first2 == __last2 + || !ranges::search(__first1, __last1, __first2, __last2, + std::move(__pred), std::move(__proj1), std::move(__proj2)).empty(); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __contains_subrange_fn contains_subrange{}; + +#endif // __glibcxx_ranges_contains + +#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 + + template + struct out_value_result + { + [[no_unique_address]] _Out out; + [[no_unique_address]] _Tp value; + + template + requires convertible_to + && convertible_to + constexpr + operator out_value_result<_Out2, _Tp2>() const & + { return {out, value}; } + + template + requires convertible_to<_Out, _Out2> + && convertible_to<_Tp, _Tp2> + constexpr + operator out_value_result<_Out2, _Tp2>() && + { return {std::move(out), std::move(value)}; } + }; + + template + using iota_result = out_value_result<_Out, _Tp>; + + struct __iota_fn + { + template _Sent, weakly_incrementable _Tp> + requires indirectly_writable<_Out, const _Tp&> + constexpr iota_result<_Out, _Tp> + operator()(_Out __first, _Sent __last, _Tp __value) const + { + while (__first != __last) + { + *__first = static_cast(__value); + ++__first; + ++__value; + } + return {std::move(__first), std::move(__value)}; + } + + template _Range> + constexpr iota_result, _Tp> + operator()(_Range&& __r, _Tp __value) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__value)); } + }; + + inline constexpr __iota_fn iota{}; + +#endif // __glibcxx_ranges_iota + +#if __glibcxx_ranges_find_last >= 202207L // C++ >= 23 + + struct __find_last_fn + { + template _Sent, typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const + { + if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) + { + _Iter __found = ranges::find(reverse_iterator<_Iter>{__last}, + reverse_iterator<_Iter>{__first}, + __value, std::move(__proj)).base(); + if (__found == __first) + return {__last, __last}; + else + return {ranges::prev(__found), __last}; + } + else + { + _Iter __found = ranges::find(__first, __last, __value, __proj); + if (__found == __last) + return {__found, __found}; + __first = __found; + for (;;) + { + __first = ranges::find(ranges::next(__first), __last, __value, __proj); + if (__first == __last) + return {__found, __first}; + __found = __first; + } + } + } + + template + requires indirect_binary_predicate, _Proj>, const _Tp*> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__proj)); } + }; + + inline constexpr __find_last_fn find_last{}; + + struct __find_last_if_fn + { + template _Sent, typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) + { + _Iter __found = ranges::find_if(reverse_iterator<_Iter>{__last}, + reverse_iterator<_Iter>{__first}, + std::move(__pred), std::move(__proj)).base(); + if (__found == __first) + return {__last, __last}; + else + return {ranges::prev(__found), __last}; + } + else + { + _Iter __found = ranges::find_if(__first, __last, __pred, __proj); + if (__found == __last) + return {__found, __found}; + __first = __found; + for (;;) + { + __first = ranges::find_if(ranges::next(__first), __last, __pred, __proj); + if (__first == __last) + return {__found, __first}; + __found = __first; + } + } + } + + template, _Proj>> _Pred> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); } + }; + + inline constexpr __find_last_if_fn find_last_if{}; + + struct __find_last_if_not_fn + { + template _Sent, typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) + { + _Iter __found = ranges::find_if_not(reverse_iterator<_Iter>{__last}, + reverse_iterator<_Iter>{__first}, + std::move(__pred), std::move(__proj)).base(); + if (__found == __first) + return {__last, __last}; + else + return {ranges::prev(__found), __last}; + } + else + { + _Iter __found = ranges::find_if_not(__first, __last, __pred, __proj); + if (__found == __last) + return {__found, __found}; + __first = __found; + for (;;) + { + __first = ranges::find_if_not(ranges::next(__first), __last, __pred, __proj); + if (__first == __last) + return {__found, __first}; + __found = __first; + } + } + } + + template, _Proj>> _Pred> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); } + }; + + inline constexpr __find_last_if_not_fn find_last_if_not{}; + +#endif // __glibcxx_ranges_find_last + +#if __glibcxx_ranges_fold >= 202207L // C++ >= 23 + + template + struct in_value_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Tp value; + + template + requires convertible_to + && convertible_to + constexpr + operator in_value_result<_Iter2, _Tp2>() const & + { return {in, value}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Tp, _Tp2> + constexpr + operator in_value_result<_Iter2, _Tp2>() && + { return {std::move(in), std::move(value)}; } + }; + + namespace __detail + { + template + class __flipped + { + _Fp _M_f; + + public: + template + requires invocable<_Fp&, _Up, _Tp> + invoke_result_t<_Fp&, _Up, _Tp> + operator()(_Tp&&, _Up&&); // not defined + }; + + template + concept __indirectly_binary_left_foldable_impl = movable<_Tp> && movable<_Up> + && convertible_to<_Tp, _Up> + && invocable<_Fp&, _Up, iter_reference_t<_Iter>> + && assignable_from<_Up&, invoke_result_t<_Fp&, _Up, iter_reference_t<_Iter>>>; + + template + concept __indirectly_binary_left_foldable = copy_constructible<_Fp> + && indirectly_readable<_Iter> + && invocable<_Fp&, _Tp, iter_reference_t<_Iter>> + && convertible_to>, + decay_t>>> + && __indirectly_binary_left_foldable_impl + <_Fp, _Tp, _Iter, decay_t>>>; + + template + concept __indirectly_binary_right_foldable + = __indirectly_binary_left_foldable<__flipped<_Fp>, _Tp, _Iter>; + } // namespace __detail + + template + using fold_left_with_iter_result = in_value_result<_Iter, _Tp>; + + struct __fold_left_with_iter_fn + { + template + static constexpr auto + _S_impl(_Iter __first, _Sent __last, _Tp __init, _Fp __f) + { + using _Up = decay_t>>; + using _Ret = fold_left_with_iter_result<_Ret_iter, _Up>; + + if (__first == __last) + return _Ret{std::move(__first), _Up(std::move(__init))}; + + _Up __accum = std::__invoke(__f, std::move(__init), *__first); + for (++__first; __first != __last; ++__first) + __accum = std::__invoke(__f, std::move(__accum), *__first); + return _Ret{std::move(__first), std::move(__accum)}; + } + + template _Sent, typename _Tp, + __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + using _Ret_iter = _Iter; + return _S_impl<_Ret_iter>(std::move(__first), __last, + std::move(__init), std::move(__f)); + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { + using _Ret_iter = borrowed_iterator_t<_Range>; + return _S_impl<_Ret_iter>(ranges::begin(__r), ranges::end(__r), + std::move(__init), std::move(__f)); + } + }; + + inline constexpr __fold_left_with_iter_fn fold_left_with_iter{}; + + struct __fold_left_fn + { + template _Sent, typename _Tp, + __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + return ranges::fold_left_with_iter(std::move(__first), __last, + std::move(__init), std::move(__f)).value; + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); } + }; + + inline constexpr __fold_left_fn fold_left{}; + + template + using fold_left_first_with_iter_result = in_value_result<_Iter, _Tp>; + + struct __fold_left_first_with_iter_fn + { + template + static constexpr auto + _S_impl(_Iter __first, _Sent __last, _Fp __f) + { + using _Up = decltype(ranges::fold_left(std::move(__first), __last, + iter_value_t<_Iter>(*__first), __f)); + using _Ret = fold_left_first_with_iter_result<_Ret_iter, optional<_Up>>; + + if (__first == __last) + return _Ret{std::move(__first), optional<_Up>()}; + + optional<_Up> __init(in_place, *__first); + for (++__first; __first != __last; ++__first) + *__init = std::__invoke(__f, std::move(*__init), *__first); + return _Ret{std::move(__first), std::move(__init)}; + } + + template _Sent, + __detail::__indirectly_binary_left_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + using _Ret_iter = _Iter; + return _S_impl<_Ret_iter>(std::move(__first), __last, std::move(__f)); + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { + using _Ret_iter = borrowed_iterator_t<_Range>; + return _S_impl<_Ret_iter>(ranges::begin(__r), ranges::end(__r), std::move(__f)); + } + }; + + inline constexpr __fold_left_first_with_iter_fn fold_left_first_with_iter{}; + + struct __fold_left_first_fn + { + template _Sent, + __detail::__indirectly_binary_left_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + return ranges::fold_left_first_with_iter(std::move(__first), __last, + std::move(__f)).value; + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__f)); } + }; + + inline constexpr __fold_left_first_fn fold_left_first{}; + + struct __fold_right_fn + { + template _Sent, typename _Tp, + __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + using _Up = decay_t, _Tp>>; + + if (__first == __last) + return _Up(std::move(__init)); + + _Iter __tail = ranges::next(__first, __last); + _Up __accum = std::__invoke(__f, *--__tail, std::move(__init)); + while (__first != __tail) + __accum = std::__invoke(__f, *--__tail, std::move(__accum)); + return __accum; + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); } + }; + + inline constexpr __fold_right_fn fold_right{}; + + struct __fold_right_last_fn + { + template _Sent, + __detail::__indirectly_binary_right_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + using _Up = decltype(ranges::fold_right(__first, __last, + iter_value_t<_Iter>(*__first), __f)); + + if (__first == __last) + return optional<_Up>(); + + _Iter __tail = ranges::prev(ranges::next(__first, std::move(__last))); + return optional<_Up>(in_place, + ranges::fold_right(std::move(__first), __tail, + iter_value_t<_Iter>(*__tail), + std::move(__f))); + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__f)); } + }; + + inline constexpr __fold_right_last_fn fold_right_last{}; +#endif // __glibcxx_ranges_fold +} // namespace ranges + + template + constexpr _ForwardIterator + shift_left(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __last; + + auto __mid = ranges::next(__first, __n, __last); + if (__mid == __last) + return __first; + return std::move(std::move(__mid), std::move(__last), std::move(__first)); + } + + template + constexpr _ForwardIterator + shift_right(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __first; + + using _Cat + = typename iterator_traits<_ForwardIterator>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + { + auto __mid = ranges::next(__last, -__n, __first); + if (__mid == __first) + return __last; + + return std::move_backward(std::move(__first), std::move(__mid), + std::move(__last)); + } + else + { + auto __result = ranges::next(__first, __n, __last); + if (__result == __last) + return __last; + + auto __dest_head = __first, __dest_tail = __result; + while (__dest_head != __result) + { + if (__dest_tail == __last) + { + // If we get here, then we must have + // 2*n >= distance(__first, __last) + // i.e. we are shifting out at least half of the range. In + // this case we can safely perform the shift with a single + // move. + std::move(std::move(__first), std::move(__dest_head), __result); + return __result; + } + ++__dest_head; + ++__dest_tail; + } + + for (;;) + { + // At the start of each iteration of this outer loop, the range + // [__first, __result) contains those elements that after shifting + // the whole range right by __n, should end up in + // [__dest_head, __dest_tail) in order. + + // The below inner loop swaps the elements of [__first, __result) + // and [__dest_head, __dest_tail), while simultaneously shifting + // the latter range by __n. + auto __cursor = __first; + while (__cursor != __result) + { + if (__dest_tail == __last) + { + // At this point the ranges [__first, result) and + // [__dest_head, dest_tail) are disjoint, so we can safely + // move the remaining elements. + __dest_head = std::move(__cursor, __result, + std::move(__dest_head)); + std::move(std::move(__first), std::move(__cursor), + std::move(__dest_head)); + return __result; + } + std::iter_swap(__cursor, __dest_head); + ++__dest_head; + ++__dest_tail; + ++__cursor; + } + } + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGO_H diff --git a/template/sysroot/include/bits/ranges_algobase.h b/template/sysroot/include/bits/ranges_algobase.h new file mode 100644 index 0000000..e26a73a --- /dev/null +++ b/template/sysroot/include/bits/ranges_algobase.h @@ -0,0 +1,601 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGOBASE_H +#define _RANGES_ALGOBASE_H 1 + +#if __cplusplus > 201703L + +#include +#include +#include +#include // ranges::begin, ranges::range etc. +#include // __invoke +#include // __is_byte + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr inline bool __is_normal_iterator = false; + + template + constexpr inline bool + __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, + _Container>> = true; + + template + constexpr inline bool __is_reverse_iterator = false; + + template + constexpr inline bool + __is_reverse_iterator> = true; + + template + constexpr inline bool __is_move_iterator = false; + + template + constexpr inline bool + __is_move_iterator> = true; + } // namespace __detail + + struct __equal_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + // TODO: implement more specializations to at least have parity with + // std::equal. + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + + using _ValueType1 = iter_value_t<_Iter1>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && __memcmpable<_Iter1, _Iter2>::__value + && is_same_v<_Pred, ranges::equal_to> + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + else + { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return true; + } + } + else + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __equal_fn equal{}; + + template + struct in_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + constexpr + operator in_out_result<_Iter2, _Out2>() const & + { return {in, out}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Out, _Out2> + constexpr + operator in_out_result<_Iter2, _Out2>() && + { return {std::move(in), std::move(out)}; } + }; + + template + using copy_result = in_out_result<_Iter, _Out>; + + template + using move_result = in_out_result<_Iter, _Out>; + + template + using move_backward_result = in_out_result<_Iter1, _Iter2>; + + template + using copy_backward_result = in_out_result<_Iter1, _Iter2>; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr __conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); + + template _Sent, + weakly_incrementable _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr __conditional_t<_IsMove, + move_result<_Iter, _Out>, + copy_result<_Iter, _Out>> + __copy_or_move(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy/std::move. + using __detail::__is_move_iterator; + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_move_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in, __out] + = ranges::__copy_or_move(std::move(__first).base(), + std::move(__last).base(), + std::move(__result)); + return {move_iterator{std::move(__in)}, std::move(__out)}; + } + else if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__first.base(), __last.base(), + std::move(__result)); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(std::move(__first), __last, __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + if (!std::__is_constant_evaluated()) + { + if constexpr (__memcpyable<_Iter, _Out>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result + __num}; + } + } + + for (auto __n = __last - __first; __n > 0; --__n) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + else + { + while (__first != __last) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + } + + struct __copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Out> + constexpr copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_fn copy{}; + + struct __move_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_movable<_Iter, _Out> + constexpr move_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Out> + constexpr move_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_fn move{}; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr __conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy_backward/std::move_backward. + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(__first.base(), + __last.base(), + std::move(__result)); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__first), + std::move(__last), + __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + if (!std::__is_constant_evaluated()) + { + if constexpr (__memcpyable<_Out, _Iter>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result - __num, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result - __num}; + } + } + + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + for (auto __n = __last - __first; __n > 0; --__n) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + else + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + while (__first != __tail) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + } + + struct __copy_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_copyable<_Iter1, _Iter2> + constexpr copy_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Iter> + constexpr copy_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_backward_fn copy_backward{}; + + struct __move_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_movable<_Iter1, _Iter2> + constexpr move_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + constexpr move_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_backward_fn move_backward{}; + + template + using copy_n_result = in_out_result<_Iter, _Out>; + + struct __copy_n_fn + { + template + requires indirectly_copyable<_Iter, _Out> + constexpr copy_n_result<_Iter, _Out> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Out __result) const + { + if constexpr (random_access_iterator<_Iter>) + { + if (__n > 0) + return ranges::copy(__first, __first + __n, std::move(__result)); + } + else + { + for (; __n > 0; --__n, (void)++__result, (void)++__first) + *__result = *__first; + } + return {std::move(__first), std::move(__result)}; + } + }; + + inline constexpr __copy_n_fn copy_n{}; + + struct __fill_n_fn + { + template _Out> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, + const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill_n + if (__n <= 0) + return __first; + + if constexpr (is_scalar_v<_Tp>) + { + // TODO: Generalize this optimization to contiguous iterators. + if constexpr (is_pointer_v<_Out> + // Note that __is_byte already implies !is_volatile. + && __is_byte>::__value + && integral<_Tp>) + { + if (!std::__is_constant_evaluated()) + { + __builtin_memset(__first, + static_cast(__value), + __n); + return __first + __n; + } + } + + const auto __tmp = __value; + for (; __n > 0; --__n, (void)++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __n > 0; --__n, (void)++__first) + *__first = __value; + return __first; + } + } + }; + + inline constexpr __fill_n_fn fill_n{}; + + struct __fill_fn + { + template _Out, sentinel_for<_Out> _Sent> + constexpr _Out + operator()(_Out __first, _Sent __last, const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill + if constexpr (sized_sentinel_for<_Sent, _Out>) + { + const auto __len = __last - __first; + return ranges::fill_n(__first, __len, __value); + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value); + } + }; + + inline constexpr __fill_fn fill{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGOBASE_H diff --git a/template/sysroot/include/bits/ranges_base.h b/template/sysroot/include/bits/ranges_base.h new file mode 100644 index 0000000..6597ffa --- /dev/null +++ b/template/sysroot/include/bits/ranges_base.h @@ -0,0 +1,1071 @@ +// Core concepts and definitions for -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_base.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ranges} + */ + +#ifndef _GLIBCXX_RANGES_BASE_H +#define _GLIBCXX_RANGES_BASE_H 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L +#include +#include +#include +#include +#include + +#ifdef __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + template + inline constexpr bool disable_sized_range = false; + + template + inline constexpr bool enable_borrowed_range = false; + + namespace __detail + { + constexpr __max_size_type + __to_unsigned_like(__max_size_type __t) noexcept + { return __t; } + + constexpr __max_size_type + __to_unsigned_like(__max_diff_type __t) noexcept + { return __max_size_type(__t); } + + template + constexpr auto + __to_unsigned_like(_Tp __t) noexcept + { return static_cast>(__t); } + +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + constexpr unsigned __int128 + __to_unsigned_like(__int128 __t) noexcept + { return __t; } + + constexpr unsigned __int128 + __to_unsigned_like(unsigned __int128 __t) noexcept + { return __t; } +#endif + + template + using __make_unsigned_like_t + = decltype(__detail::__to_unsigned_like(std::declval<_Tp>())); + + // Part of the constraints of ranges::borrowed_range + template + concept __maybe_borrowed_range + = is_lvalue_reference_v<_Tp> + || enable_borrowed_range>; + + } // namespace __detail + + // Namespace for helpers for the customization points. + namespace __access + { + using std::ranges::__detail::__maybe_borrowed_range; + using std::__detail::__range_iter_t; + + struct _Begin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_array_v>) + return true; + else if constexpr (__member_begin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().begin())); + else + return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_array_v> || __member_begin<_Tp> + || __adl_begin<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (is_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + return __t + 0; + } + else if constexpr (__member_begin<_Tp>) + return __t.begin(); + else + return begin(__t); + } + }; + + template + concept __member_end = requires(_Tp& __t) + { + { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>; + }; + + // Poison pill so that unqualified lookup doesn't find std::end. + void end() = delete; + + template + concept __adl_end = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; + }; + + struct _End + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_end<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().end())); + else + return noexcept(__decay_copy(end(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_bounded_array_v> + || __member_end<_Tp> || __adl_end<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (is_bounded_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + return __t + extent_v>; + } + else if constexpr (__member_end<_Tp>) + return __t.end(); + else + return end(__t); + } + }; + + template + concept __member_rbegin = requires(_Tp& __t) + { + { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; + }; + + void rbegin() = delete; + + template + concept __adl_rbegin = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; + }; + + template + concept __reversable = requires(_Tp& __t) + { + { _Begin{}(__t) } -> bidirectional_iterator; + { _End{}(__t) } -> same_as; + }; + + struct _RBegin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rbegin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); + else if constexpr (__adl_rbegin<_Tp>) + return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) + { + using _It = decltype(_End{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const + noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (__member_rbegin<_Tp>) + return __t.rbegin(); + else if constexpr (__adl_rbegin<_Tp>) + return rbegin(__t); + else + return std::make_reverse_iterator(_End{}(__t)); + } + }; + + template + concept __member_rend = requires(_Tp& __t) + { + { __decay_copy(__t.rend()) } + -> sentinel_for(__t)))>; + }; + + void rend() = delete; + + template + concept __adl_rend = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rend(__t)) } + -> sentinel_for(__t)))>; + }; + + struct _REnd + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rend<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rend())); + else if constexpr (__adl_rend<_Tp>) + return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) + { + using _It = decltype(_Begin{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const + noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (__member_rend<_Tp>) + return __t.rend(); + else if constexpr (__adl_rend<_Tp>) + return rend(__t); + else + return std::make_reverse_iterator(_Begin{}(__t)); + } + }; + + template + concept __member_size = !disable_sized_range> + && requires(_Tp& __t) + { + { __decay_copy(__t.size()) } -> __detail::__is_integer_like; + }; + + void size() = delete; + + template + concept __adl_size = __class_or_enum> + && !disable_sized_range> + && requires(_Tp& __t) + { + { __decay_copy(size(__t)) } -> __detail::__is_integer_like; + }; + + template + concept __sentinel_size = requires(_Tp& __t) + { + requires (!is_unbounded_array_v>); + + { _Begin{}(__t) } -> forward_iterator; + + { _End{}(__t) } -> sized_sentinel_for; + + __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t)); + }; + + struct _Size + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_size<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().size())); + else if constexpr (__adl_size<_Tp>) + return noexcept(__decay_copy(size(std::declval<_Tp&>()))); + else if constexpr (__sentinel_size<_Tp>) + return noexcept(_End{}(std::declval<_Tp&>()) + - _Begin{}(std::declval<_Tp&>())); + } + + public: + template + requires is_bounded_array_v> + || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (is_bounded_array_v>) + return extent_v>; + else if constexpr (__member_size<_Tp>) + return __t.size(); + else if constexpr (__adl_size<_Tp>) + return size(__t); + else if constexpr (__sentinel_size<_Tp>) + return __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t)); + } + }; + + struct _SSize + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E) + template + requires requires (_Tp& __t) { _Size{}(__t); } + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const noexcept(noexcept(_Size{}(__t))) + { + auto __size = _Size{}(__t); + using __size_type = decltype(__size); + // Return the wider of ptrdiff_t and make-signed-like-t<__size_type>. + if constexpr (integral<__size_type>) + { + using __gnu_cxx::__int_traits; + if constexpr (__int_traits<__size_type>::__digits + < __int_traits::__digits) + return static_cast(__size); + else + return static_cast>(__size); + } +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // For strict-ansi modes integral<__int128> is false + else if constexpr (__detail::__is_int128<__size_type>) + return static_cast<__int128>(__size); +#endif + else // Must be one of __max_diff_type or __max_size_type. + return __detail::__max_diff_type(__size); + } + }; + + template + concept __member_empty = requires(_Tp& __t) { bool(__t.empty()); }; + + template + concept __size0_empty = requires(_Tp& __t) { _Size{}(__t) == 0; }; + + template + concept __eq_iter_empty = requires(_Tp& __t) + { + requires (!is_unbounded_array_v>); + + { _Begin{}(__t) } -> forward_iterator; + + bool(_Begin{}(__t) == _End{}(__t)); + }; + + struct _Empty + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_empty<_Tp>) + return noexcept(bool(std::declval<_Tp&>().empty())); + else if constexpr (__size0_empty<_Tp>) + return noexcept(_Size{}(std::declval<_Tp&>()) == 0); + else + return noexcept(bool(_Begin{}(std::declval<_Tp&>()) + == _End{}(std::declval<_Tp&>()))); + } + + public: + template + requires __member_empty<_Tp> || __size0_empty<_Tp> + || __eq_iter_empty<_Tp> + constexpr bool + operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + { + if constexpr (__member_empty<_Tp>) + return bool(__t.empty()); + else if constexpr (__size0_empty<_Tp>) + return _Size{}(__t) == 0; + else + return bool(_Begin{}(__t) == _End{}(__t)); + } + }; + + template + concept __pointer_to_object = is_pointer_v<_Tp> + && is_object_v>; + + template + concept __member_data = requires(_Tp& __t) + { + { __decay_copy(__t.data()) } -> __pointer_to_object; + }; + + template + concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>; + + struct _Data + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_data<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().data())); + else + return noexcept(_Begin{}(std::declval<_Tp&>())); + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_data<_Tp> || __begin_data<_Tp> + constexpr auto + operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_data<_Tp>) + return __t.data(); + else + return std::to_address(_Begin{}(__t)); + } + }; + + } // namespace __access + + inline namespace _Cpo + { + inline constexpr ranges::__access::_Begin begin{}; + inline constexpr ranges::__access::_End end{}; + inline constexpr ranges::__access::_RBegin rbegin{}; + inline constexpr ranges::__access::_REnd rend{}; + inline constexpr ranges::__access::_Size size{}; + inline constexpr ranges::__access::_SSize ssize{}; + inline constexpr ranges::__access::_Empty empty{}; + inline constexpr ranges::__access::_Data data{}; + } + + /// [range.range] The range concept. + template + concept range = requires(_Tp& __t) + { + ranges::begin(__t); + ranges::end(__t); + }; + + /// [range.range] The borrowed_range concept. + template + concept borrowed_range + = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; + + template + using iterator_t = std::__detail::__range_iter_t<_Tp>; + + template + using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); + +#if __cplusplus > 202002L + template + using const_iterator_t = const_iterator>; + + template + using const_sentinel_t = const_sentinel>; + + template + using range_const_reference_t = iter_const_reference_t>; +#endif + + template + using range_difference_t = iter_difference_t>; + + template + using range_value_t = iter_value_t>; + + template + using range_reference_t = iter_reference_t>; + + template + using range_rvalue_reference_t + = iter_rvalue_reference_t>; + + /// [range.sized] The sized_range concept. + template + concept sized_range = range<_Tp> + && requires(_Tp& __t) { ranges::size(__t); }; + + template + using range_size_t = decltype(ranges::size(std::declval<_Range&>())); + + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface; // defined in + + namespace __detail + { + template + requires (!same_as<_Tp, view_interface<_Up>>) + void __is_derived_from_view_interface_fn(const _Tp&, + const view_interface<_Up>&); // not defined + + // Returns true iff _Tp has exactly one public base class that's a + // specialization of view_interface. + template + concept __is_derived_from_view_interface + = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); }; + } // namespace __detail + + /// [range.view] The ranges::view_base type. + struct view_base { }; + + /// [range.view] The ranges::enable_view boolean. + template + inline constexpr bool enable_view = derived_from<_Tp, view_base> + || __detail::__is_derived_from_view_interface<_Tp>; + + /// [range.view] The ranges::view concept. + template + concept view + = range<_Tp> && movable<_Tp> && enable_view<_Tp>; + + // [range.refinements] + + /// A range for which ranges::begin returns an output iterator. + template + concept output_range + = range<_Range> && output_iterator, _Tp>; + + /// A range for which ranges::begin returns an input iterator. + template + concept input_range = range<_Tp> && input_iterator>; + + /// A range for which ranges::begin returns a forward iterator. + template + concept forward_range + = input_range<_Tp> && forward_iterator>; + + /// A range for which ranges::begin returns a bidirectional iterator. + template + concept bidirectional_range + = forward_range<_Tp> && bidirectional_iterator>; + + /// A range for which ranges::begin returns a random access iterator. + template + concept random_access_range + = bidirectional_range<_Tp> && random_access_iterator>; + + /// A range for which ranges::begin returns a contiguous iterator. + template + concept contiguous_range + = random_access_range<_Tp> && contiguous_iterator> + && requires(_Tp& __t) + { + { ranges::data(__t) } -> same_as>>; + }; + + /// A range for which ranges::begin and ranges::end return the same type. + template + concept common_range + = range<_Tp> && same_as, sentinel_t<_Tp>>; + +#if __cplusplus > 202002L + template + concept constant_range + = input_range<_Tp> && std::__detail::__constant_iterator>; +#endif + + namespace __access + { +#if __cplusplus > 202020L + template + constexpr auto& + __possibly_const_range(_Range& __r) noexcept + { + if constexpr (constant_range && !constant_range<_Range>) + return const_cast(__r); + else + return __r; + } +#else + // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&. + template + constexpr decltype(auto) + __as_const(_Tp& __t) noexcept + { + static_assert(std::is_same_v<_To&, _Tp&>); + + if constexpr (is_lvalue_reference_v<_To>) + return const_cast(__t); + else + return static_cast(__t); + } +#endif + + struct _CBegin + { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_iterator + (ranges::begin(__access::__possibly_const_range(__t))))) + requires requires { std::make_const_iterator + (ranges::begin(__access::__possibly_const_range(__t))); } + { + auto& __r = __access::__possibly_const_range(__t); + return const_iterator_t(ranges::begin(__r)); + } +#else + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Begin{}(__access::__as_const<_Tp>(__e)))) + requires requires { _Begin{}(__access::__as_const<_Tp>(__e)); } + { + return _Begin{}(__access::__as_const<_Tp>(__e)); + } +#endif + }; + + struct _CEnd final + { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_sentinel + (ranges::end(__access::__possibly_const_range(__t))))) + requires requires { std::make_const_sentinel + (ranges::end(__access::__possibly_const_range(__t))); } + { + auto& __r = __access::__possibly_const_range(__t); + return const_sentinel_t(ranges::end(__r)); + } +#else + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_End{}(__access::__as_const<_Tp>(__e)))) + requires requires { _End{}(__access::__as_const<_Tp>(__e)); } + { + return _End{}(__access::__as_const<_Tp>(__e)); + } +#endif + }; + + struct _CRBegin + { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_iterator + (ranges::rbegin(__access::__possibly_const_range(__t))))) + requires requires { std::make_const_iterator + (ranges::rbegin(__access::__possibly_const_range(__t))); } + { + auto& __r = __access::__possibly_const_range(__t); + return const_iterator(ranges::rbegin(__r)); + } +#else + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_RBegin{}(__access::__as_const<_Tp>(__e)))) + requires requires { _RBegin{}(__access::__as_const<_Tp>(__e)); } + { + return _RBegin{}(__access::__as_const<_Tp>(__e)); + } +#endif + }; + + struct _CREnd + { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_sentinel + (ranges::rend(__access::__possibly_const_range(__t))))) + requires requires { std::make_const_sentinel + (ranges::rend(__access::__possibly_const_range(__t))); } + { + auto& __r = __access::__possibly_const_range(__t); + return const_sentinel(ranges::rend(__r)); + } +#else + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_REnd{}(__access::__as_const<_Tp>(__e)))) + requires requires { _REnd{}(__access::__as_const<_Tp>(__e)); } + { + return _REnd{}(__access::__as_const<_Tp>(__e)); + } +#endif + }; + + struct _CData + { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr const auto* + operator()(_Tp&& __t) const + noexcept(noexcept(ranges::data(__access::__possibly_const_range(__t)))) + requires requires { ranges::data(__access::__possibly_const_range(__t)); } + { return ranges::data(__access::__possibly_const_range(__t)); } +#else + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Data{}(__access::__as_const<_Tp>(__e)))) + requires requires { _Data{}(__access::__as_const<_Tp>(__e)); } + { + return _Data{}(__access::__as_const<_Tp>(__e)); + } +#endif + }; + } // namespace __access + + inline namespace _Cpo + { + inline constexpr ranges::__access::_CBegin cbegin{}; + inline constexpr ranges::__access::_CEnd cend{}; + inline constexpr ranges::__access::_CRBegin crbegin{}; + inline constexpr ranges::__access::_CREnd crend{}; + inline constexpr ranges::__access::_CData cdata{}; + } + + namespace __detail + { + template + inline constexpr bool __is_initializer_list = false; + + template + inline constexpr bool __is_initializer_list> = true; + } // namespace __detail + + /// A range which can be safely converted to a view. + template + concept viewable_range = range<_Tp> + && ((view> && constructible_from, _Tp>) + || (!view> + && (is_lvalue_reference_v<_Tp> + || (movable> + && !__detail::__is_initializer_list>)))); + + // [range.iter.ops] range iterator operations + + struct __advance_fn final + { + template + constexpr void + operator()(_It& __it, iter_difference_t<_It> __n) const + { + if constexpr (random_access_iterator<_It>) + __it += __n; + else if constexpr (bidirectional_iterator<_It>) + { + if (__n > 0) + { + do + { + ++__it; + } + while (--__n); + } + else if (__n < 0) + { + do + { + --__it; + } + while (++__n); + } + } + else + { + // cannot decrement a non-bidirectional iterator + __glibcxx_assert(__n >= 0); + while (__n-- > 0) + ++__it; + } + } + + template _Sent> + constexpr void + operator()(_It& __it, _Sent __bound) const + { + if constexpr (assignable_from<_It&, _Sent>) + __it = std::move(__bound); + else if constexpr (sized_sentinel_for<_Sent, _It>) + (*this)(__it, __bound - __it); + else + { + while (__it != __bound) + ++__it; + } + } + + template _Sent> + constexpr iter_difference_t<_It> + operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound) const + { + if constexpr (sized_sentinel_for<_Sent, _It>) + { + const auto __diff = __bound - __it; + + if (__diff == 0) + return __n; + else if (__diff > 0 ? __n >= __diff : __n <= __diff) + { + (*this)(__it, __bound); + return __n - __diff; + } + else if (__n != 0) [[likely]] + { + // n and bound must not lead in opposite directions: + __glibcxx_assert((__n < 0) == (__diff < 0)); + + (*this)(__it, __n); + return 0; + } + else + return 0; + } + else if (__it == __bound || __n == 0) + return __n; + else if (__n > 0) + { + iter_difference_t<_It> __m = 0; + do + { + ++__it; + ++__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>) + { + iter_difference_t<_It> __m = 0; + do + { + --__it; + --__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else + { + // cannot decrement a non-bidirectional iterator + __glibcxx_assert(__n >= 0); + return __n; + } + } + + void operator&() const = delete; + }; + + inline constexpr __advance_fn advance{}; + + struct __distance_fn final + { + template _Sent> + requires (!sized_sentinel_for<_Sent, _It>) + constexpr iter_difference_t<_It> + operator()[[nodiscard]](_It __first, _Sent __last) const + { + iter_difference_t<_It> __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + + template _Sent> + [[nodiscard]] + constexpr iter_difference_t<_It> + operator()(const _It& __first, const _Sent& __last) const + { + return __last - __first; + } + + template + [[nodiscard]] + constexpr range_difference_t<_Range> + operator()(_Range&& __r) const + { + if constexpr (sized_range<_Range>) + return static_cast>(ranges::size(__r)); + else + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + + void operator&() const = delete; + }; + + inline constexpr __distance_fn distance{}; + + struct __next_fn final + { + template + [[nodiscard]] + constexpr _It + operator()(_It __x) const + { + ++__x; + return __x; + } + + template + [[nodiscard]] + constexpr _It + operator()(_It __x, iter_difference_t<_It> __n) const + { + ranges::advance(__x, __n); + return __x; + } + + template _Sent> + [[nodiscard]] + constexpr _It + operator()(_It __x, _Sent __bound) const + { + ranges::advance(__x, __bound); + return __x; + } + + template _Sent> + [[nodiscard]] + constexpr _It + operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const + { + ranges::advance(__x, __n, __bound); + return __x; + } + + void operator&() const = delete; + }; + + inline constexpr __next_fn next{}; + + struct __prev_fn final + { + template + [[nodiscard]] + constexpr _It + operator()(_It __x) const + { + --__x; + return __x; + } + + template + [[nodiscard]] + constexpr _It + operator()(_It __x, iter_difference_t<_It> __n) const + { + ranges::advance(__x, -__n); + return __x; + } + + template + [[nodiscard]] + constexpr _It + operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const + { + ranges::advance(__x, -__n, __bound); + return __x; + } + + void operator&() const = delete; + }; + + inline constexpr __prev_fn prev{}; + + /// Type returned by algorithms instead of a dangling iterator or subrange. + struct dangling + { + constexpr dangling() noexcept = default; + template + constexpr dangling(_Args&&...) noexcept { } + }; + + template + using borrowed_iterator_t = __conditional_t, + iterator_t<_Range>, + dangling>; +} // namespace ranges + +#if __glibcxx_ranges_to_container // C++ >= 23 + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // library concepts +#endif // C++20 +#endif // _GLIBCXX_RANGES_BASE_H diff --git a/template/sysroot/include/bits/ranges_cmp.h b/template/sysroot/include/bits/ranges_cmp.h new file mode 100644 index 0000000..8425016 --- /dev/null +++ b/template/sysroot/include/bits/ranges_cmp.h @@ -0,0 +1,179 @@ +// Concept-constrained comparison implementations -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_cmp.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _RANGES_CMP_H +#define _RANGES_CMP_H 1 + +#if __cplusplus > 201703L +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __is_transparent; // not defined + + // Define std::identity here so that and + // don't need to include to get it. + + /// [func.identity] The identity function. + struct identity + { + template + [[nodiscard]] + constexpr _Tp&& + operator()(_Tp&& __t) const noexcept + { return std::forward<_Tp>(__t); } + + using is_transparent = __is_transparent; + }; + +#ifdef __glibcxx_ranges // C++ >= 20 +namespace ranges +{ + namespace __detail + { + // BUILTIN-PTR-CMP(T, <, U) + // This determines whether t < u results in a call to a built-in operator< + // comparing pointers. It doesn't work for function pointers (PR 93628). + template + concept __less_builtin_ptr_cmp + = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as; } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && (! requires(_Tp&& __t, _Up&& __u) + { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); }); + } // namespace __detail + + // [range.cmp] Concept-constrained comparisons + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks + + /// ranges::equal_to function object type. + struct equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + using is_transparent = __is_transparent; + }; + + /// ranges::not_equal_to function object type. + struct not_equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>())) + { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less function object type. + struct less + { + template + requires totally_ordered_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { + if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) + { + if (std::__is_constant_evaluated()) + return __t < __u; + + auto __x = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Tp>(__t))); + auto __y = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Up>(__u))); + return __x < __y; + } + else + return std::forward<_Tp>(__t) < std::forward<_Up>(__u); + } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater function object type. + struct greater + { + template + requires totally_ordered_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater_equal function object type. + struct greater_equal + { + template + requires totally_ordered_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less_equal function object type. + struct less_equal + { + template + requires totally_ordered_with<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + +} // namespace ranges +#endif // __glibcxx_ranges +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _RANGES_CMP_H diff --git a/template/sysroot/include/bits/ranges_uninitialized.h b/template/sysroot/include/bits/ranges_uninitialized.h new file mode 100644 index 0000000..f16f2ef --- /dev/null +++ b/template/sysroot/include/bits/ranges_uninitialized.h @@ -0,0 +1,574 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2020-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _RANGES_UNINITIALIZED_H +#define _RANGES_UNINITIALIZED_H 1 + +#if __cplusplus > 201703L +#if __cpp_lib_concepts + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr void* + __voidify(_Tp& __obj) noexcept + { + return const_cast + (static_cast(std::__addressof(__obj))); + } + + template + concept __nothrow_input_iterator + = (input_iterator<_Iter> + && is_lvalue_reference_v> + && same_as>, + iter_value_t<_Iter>>); + + template + concept __nothrow_sentinel = sentinel_for<_Sent, _Iter>; + + template + concept __nothrow_input_range + = (range<_Range> + && __nothrow_input_iterator> + && __nothrow_sentinel, iterator_t<_Range>>); + + template + concept __nothrow_forward_iterator + = (__nothrow_input_iterator<_Iter> + && forward_iterator<_Iter> + && __nothrow_sentinel<_Iter, _Iter>); + + template + concept __nothrow_forward_range + = (__nothrow_input_range<_Range> + && __nothrow_forward_iterator>); + } // namespace __detail + + struct __destroy_fn + { + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const noexcept; + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const noexcept; + }; + + inline constexpr __destroy_fn destroy{}; + + namespace __detail + { + template + requires destructible> + struct _DestroyGuard + { + private: + _Iter _M_first; + const _Iter* _M_cur; + + public: + explicit + _DestroyGuard(const _Iter& __iter) + : _M_first(__iter), _M_cur(std::__addressof(__iter)) + { } + + void + release() noexcept + { _M_cur = nullptr; } + + ~_DestroyGuard() + { + if (_M_cur != nullptr) + ranges::destroy(std::move(_M_first), *_M_cur); + } + }; + + template + requires destructible> + && is_trivially_destructible_v> + struct _DestroyGuard<_Iter> + { + explicit + _DestroyGuard(const _Iter&) + { } + + void + release() noexcept + { } + }; + } // namespace __detail + + struct __uninitialized_default_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __last); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_default_construct_fn + uninitialized_default_construct{}; + + struct __uninitialized_default_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __n); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_default_construct_n_fn + uninitialized_default_construct_n; + + struct __uninitialized_value_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill(__first, __last, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_value_construct_fn + uninitialized_value_construct{}; + + struct __uninitialized_value_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill_n(__first, __n, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_value_construct_n_fn + uninitialized_value_construct_n; + + template + using uninitialized_copy_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_reference_t<_IRange>> + uninitialized_copy_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_copy_fn uninitialized_copy{}; + + template + using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_n_fn + { + template _Sent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__n, __d), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; + + template + using uninitialized_move_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__d1, __d2), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_rvalue_reference_t<_IRange>> + uninitialized_move_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_move_fn uninitialized_move{}; + + template + using uninitialized_move_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_n_fn + { + template _Sent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__n, __d), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; + + struct __uninitialized_fill_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, _Sent __last, const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill(__first, __last, __x); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range, typename _Tp> + requires constructible_from, const _Tp&> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __x) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __x); + } + }; + + inline constexpr __uninitialized_fill_fn uninitialized_fill{}; + + struct __uninitialized_fill_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, + const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill_n(__first, __n, __x); + else + { + auto __guard = __detail::_DestroyGuard(__first); + for (; __n > 0; ++__first, (void)--__n) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; + + struct __construct_at_fn + { + template + requires requires { + ::new (std::declval()) _Tp(std::declval<_Args>()...); + } + constexpr _Tp* + operator()(_Tp* __location, _Args&&... __args) const + noexcept(noexcept(std::construct_at(__location, + std::forward<_Args>(__args)...))) + { + return std::construct_at(__location, + std::forward<_Args>(__args)...); + } + }; + + inline constexpr __construct_at_fn construct_at{}; + + struct __destroy_at_fn + { + template + constexpr void + operator()(_Tp* __location) const noexcept + { + if constexpr (is_array_v<_Tp>) + ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); + else + __location->~_Tp(); + } + }; + + inline constexpr __destroy_at_fn destroy_at{}; + + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __last); + else + { + for (; __first != __last; ++__first) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + __destroy_fn::operator()(_Range&& __r) const noexcept + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + + struct __destroy_n_fn + { + template<__detail::__nothrow_input_iterator _Iter> + requires destructible> + constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __n); + else + { + for (; __n > 0; ++__first, (void)--__n) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + }; + + inline constexpr __destroy_n_fn destroy_n{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_UNINITIALIZED_H diff --git a/template/sysroot/include/bits/ranges_util.h b/template/sysroot/include/bits/ranges_util.h new file mode 100644 index 0000000..9b79c3a --- /dev/null +++ b/template/sysroot/include/bits/ranges_util.h @@ -0,0 +1,823 @@ +// Utilities for representing and manipulating ranges -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_util.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ranges} + */ + +#ifndef _RANGES_UTIL_H +#define _RANGES_UTIL_H 1 + +#if __cplusplus > 201703L +# include +# include +# include + +#ifdef __glibcxx_ranges +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + // C++20 24.5 [range.utility] Range utilities + + namespace __detail + { + template + concept __simple_view = view<_Range> && range + && same_as, iterator_t> + && same_as, sentinel_t>; + + template + concept __has_arrow = input_iterator<_It> + && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); }); + + using std::__detail::__different_from; + } // namespace __detail + + /// The ranges::view_interface class template + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface + { + private: + constexpr _Derived& _M_derived() noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast<_Derived&>(*this); + } + + constexpr const _Derived& _M_derived() const noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast(*this); + } + + static constexpr bool + _S_bool(bool) noexcept; // not defined + + template + static constexpr bool + _S_empty(_Tp& __t) + noexcept(noexcept(_S_bool(ranges::begin(__t) == ranges::end(__t)))) + { return ranges::begin(__t) == ranges::end(__t); } + + template + static constexpr auto + _S_size(_Tp& __t) + noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) + { return ranges::end(__t) - ranges::begin(__t); } + + public: + constexpr bool + empty() + noexcept(noexcept(_S_empty(_M_derived()))) + requires forward_range<_Derived> && (!sized_range<_Derived>) + { return _S_empty(_M_derived()); } + + constexpr bool + empty() + noexcept(noexcept(ranges::size(_M_derived()) == 0)) + requires sized_range<_Derived> + { return ranges::size(_M_derived()) == 0; } + + constexpr bool + empty() const + noexcept(noexcept(_S_empty(_M_derived()))) + requires forward_range && (!sized_range) + { return _S_empty(_M_derived()); } + + constexpr bool + empty() const + noexcept(noexcept(ranges::size(_M_derived()) == 0)) + requires sized_range + { return ranges::size(_M_derived()) == 0; } + + constexpr explicit + operator bool() noexcept(noexcept(ranges::empty(_M_derived()))) + requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr explicit + operator bool() const noexcept(noexcept(ranges::empty(_M_derived()))) + requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr auto + data() noexcept(noexcept(ranges::begin(_M_derived()))) + requires contiguous_iterator> + { return std::to_address(ranges::begin(_M_derived())); } + + constexpr auto + data() const noexcept(noexcept(ranges::begin(_M_derived()))) + requires range + && contiguous_iterator> + { return std::to_address(ranges::begin(_M_derived())); } + + constexpr auto + size() noexcept(noexcept(_S_size(_M_derived()))) + requires forward_range<_Derived> + && sized_sentinel_for, iterator_t<_Derived>> + { return _S_size(_M_derived()); } + + constexpr auto + size() const noexcept(noexcept(_S_size(_M_derived()))) + requires forward_range + && sized_sentinel_for, + iterator_t> + { return _S_size(_M_derived()); } + + constexpr decltype(auto) + front() requires forward_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + front() const requires forward_range + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + back() + requires bidirectional_range<_Derived> && common_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + constexpr decltype(auto) + back() const + requires bidirectional_range + && common_range + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) + { return ranges::begin(_M_derived())[__n]; } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) const + { return ranges::begin(_M_derived())[__n]; } + +#if __cplusplus > 202002L + constexpr auto + cbegin() requires input_range<_Derived> + { return ranges::cbegin(_M_derived()); } + + constexpr auto + cbegin() const requires input_range + { return ranges::cbegin(_M_derived()); } + + constexpr auto + cend() requires input_range<_Derived> + { return ranges::cend(_M_derived()); } + + constexpr auto + cend() const requires input_range + { return ranges::cend(_M_derived()); } +#endif + }; + + namespace __detail + { + template + concept __uses_nonqualification_pointer_conversion + = is_pointer_v<_From> && is_pointer_v<_To> + && !convertible_to(*)[], + remove_pointer_t<_To>(*)[]>; + + template + concept __convertible_to_non_slicing = convertible_to<_From, _To> + && !__uses_nonqualification_pointer_conversion, + decay_t<_To>>; + +#if __glibcxx_tuple_like // >= C++23 + // P2165R4 version of __pair_like is defined in . +#else + // C++20 version of __pair_like from P2321R2. + template + concept __pair_like + = !is_reference_v<_Tp> && requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires derived_from, integral_constant>; + typename tuple_element_t<0, remove_const_t<_Tp>>; + typename tuple_element_t<1, remove_const_t<_Tp>>; + { get<0>(__t) } -> convertible_to&>; + { get<1>(__t) } -> convertible_to&>; + }; +#endif + + template + concept __pair_like_convertible_from + = !range<_Tp> && !is_reference_v<_Vp> && __pair_like<_Tp> + && constructible_from<_Tp, _Up, _Vp> + && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>> + && convertible_to<_Vp, tuple_element_t<1, _Tp>>; + + } // namespace __detail + + namespace views { struct _Drop; } // defined in + + enum class subrange_kind : bool { unsized, sized }; + + /// The ranges::subrange class template + template _Sent = _It, + subrange_kind _Kind = sized_sentinel_for<_Sent, _It> + ? subrange_kind::sized : subrange_kind::unsized> + requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>) + class subrange : public view_interface> + { + private: + static constexpr bool _S_store_size + = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>; + + friend struct views::_Drop; // Needs to inspect _S_store_size. + + _It _M_begin = _It(); + [[no_unique_address]] _Sent _M_end = _Sent(); + + using __size_type + = __detail::__make_unsigned_like_t>; + + template + struct _Size + { + [[__gnu__::__always_inline__]] + constexpr _Size(_Tp = {}) { } + }; + + template + struct _Size<_Tp, true> + { + [[__gnu__::__always_inline__]] + constexpr _Size(_Tp __s = {}) : _M_size(__s) { } + + _Tp _M_size; + }; + + [[no_unique_address]] _Size<__size_type> _M_size = {}; + + public: + subrange() requires default_initializable<_It> = default; + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) + noexcept(is_nothrow_constructible_v<_It, decltype(__i)> + && is_nothrow_constructible_v<_Sent, _Sent&>) + requires (!_S_store_size) + : _M_begin(std::move(__i)), _M_end(__s) + { } + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, + __size_type __n) + noexcept(is_nothrow_constructible_v<_It, decltype(__i)> + && is_nothrow_constructible_v<_Sent, _Sent&>) + requires (_Kind == subrange_kind::sized) + : _M_begin(std::move(__i)), _M_end(__s), _M_size(__n) + { } + + template<__detail::__different_from _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) + noexcept(noexcept(subrange(__r, ranges::size(__r)))) + requires _S_store_size && sized_range<_Rng> + : subrange(__r, ranges::size(__r)) + { } + + template<__detail::__different_from _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) + noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r)))) + requires (!_S_store_size) + : subrange(ranges::begin(__r), ranges::end(__r)) + { } + + template + requires __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r, __size_type __n) + noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r), __n))) + requires (_Kind == subrange_kind::sized) + : subrange{ranges::begin(__r), ranges::end(__r), __n} + { } + + template<__detail::__different_from _PairLike> + requires __detail::__pair_like_convertible_from<_PairLike, const _It&, + const _Sent&> + constexpr + operator _PairLike() const + { return _PairLike(_M_begin, _M_end); } + + constexpr _It + begin() const requires copyable<_It> + { return _M_begin; } + + [[nodiscard]] constexpr _It + begin() requires (!copyable<_It>) + { return std::move(_M_begin); } + + constexpr _Sent end() const { return _M_end; } + + constexpr bool empty() const { return _M_begin == _M_end; } + + constexpr __size_type + size() const requires (_Kind == subrange_kind::sized) + { + if constexpr (_S_store_size) + return _M_size._M_size; + else + return __detail::__to_unsigned_like(_M_end - _M_begin); + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) const & + requires forward_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(__n); + return __tmp; + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) && + { + advance(__n); + return std::move(*this); + } + + [[nodiscard]] constexpr subrange + prev(iter_difference_t<_It> __n = 1) const + requires bidirectional_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(-__n); + return __tmp; + } + + constexpr subrange& + advance(iter_difference_t<_It> __n) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3433. subrange::advance(n) has UB when n < 0 + if constexpr (bidirectional_iterator<_It>) + if (__n < 0) + { + ranges::advance(_M_begin, __n); + if constexpr (_S_store_size) + _M_size._M_size += __detail::__to_unsigned_like(-__n); + return *this; + } + + __glibcxx_assert(__n >= 0); + auto __d = __n - ranges::advance(_M_begin, __n, _M_end); + if constexpr (_S_store_size) + _M_size._M_size -= __detail::__to_unsigned_like(__d); + return *this; + } + }; + + template _Sent> + subrange(_It, _Sent) -> subrange<_It, _Sent>; + + template _Sent> + subrange(_It, _Sent, + __detail::__make_unsigned_like_t>) + -> subrange<_It, _Sent, subrange_kind::sized>; + + template + subrange(_Rng&&) + -> subrange, sentinel_t<_Rng>, + (sized_range<_Rng> + || sized_sentinel_for, iterator_t<_Rng>>) + ? subrange_kind::sized : subrange_kind::unsized>; + + template + subrange(_Rng&&, + __detail::__make_unsigned_like_t>) + -> subrange, sentinel_t<_Rng>, subrange_kind::sized>; + + template + requires (_Num < 2) + constexpr auto + get(const subrange<_It, _Sent, _Kind>& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template + requires (_Num < 2) + constexpr auto + get(subrange<_It, _Sent, _Kind>&& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template + inline constexpr bool + enable_borrowed_range> = true; + + template + using borrowed_subrange_t = __conditional_t, + subrange>, + dangling>; + + // __is_subrange is defined in . + template + inline constexpr bool __detail::__is_subrange> = true; +} // namespace ranges + +#if __glibcxx_tuple_like // >= C++23 + // __is_tuple_like_v is defined in . + template + inline constexpr bool __is_tuple_like_v> = true; +#endif + +// The following ranges algorithms are used by , and are defined here +// so that can avoid including all of . +namespace ranges +{ + struct __find_fn + { + template _Sent, typename _Tp, + typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + while (__first != __last + && !(std::__invoke(__proj, *__first) == __value)) + ++__first; + return __first; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __find_fn find{}; + + struct __find_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_fn find_if{}; + + struct __find_if_not_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_not_fn find_if_not{}; + + template + struct in_in_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + + template + requires convertible_to + && convertible_to + constexpr + operator in_in_result<_IIter1, _IIter2>() const & + { return {in1, in2}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + constexpr + operator in_in_result<_IIter1, _IIter2>() && + { return {std::move(in1), std::move(in2)}; } + }; + + template + using mismatch_result = in_in_result<_Iter1, _Iter2>; + + struct __mismatch_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr mismatch_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr mismatch_result, iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __mismatch_fn mismatch{}; + + struct __search_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__first1 == __last1 || __first2 == __last2) + return {__first1, __first1}; + + for (;;) + { + for (;;) + { + if (__first1 == __last1) + return {__first1, __first1}; + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + auto __cur1 = __first1; + auto __cur2 = __first2; + for (;;) + { + if (++__cur2 == __last2) + return {__first1, ++__cur1}; + if (++__cur1 == __last1) + return {__cur1, __cur1}; + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__cur1), + std::__invoke(__proj2, *__cur2))) + { + ++__first1; + break; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __search_fn search{}; + + struct __min_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(__comp, + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_fn min{}; + + struct __adjacent_find_fn + { + template _Sent, + typename _Proj = identity, + indirect_binary_predicate, + projected<_Iter, _Proj>> _Pred + = ranges::equal_to> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + auto __next = __first; + for (; ++__next != __last; __first = __next) + { + if (std::__invoke(__pred, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + return __first; + } + return __next; + } + + template, _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __adjacent_find_fn adjacent_find{}; + +} // namespace ranges + + using ranges::get; + + template + struct tuple_size> + : integral_constant + { }; + + template + struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + + template + struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // library concepts +#endif // C++20 +#endif // _RANGES_UTIL_H diff --git a/template/sysroot/include/bits/refwrap.h b/template/sysroot/include/bits/refwrap.h new file mode 100644 index 0000000..71ec2b2 --- /dev/null +++ b/template/sysroot/include/bits/refwrap.h @@ -0,0 +1,462 @@ +// Implementation of std::reference_wrapper -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/refwrap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_REFWRAP_H +#define _GLIBCXX_REFWRAP_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L + +#include +#include +#include // for unary_function and binary_function + +#if __glibcxx_reference_wrapper >= 202403L // >= C++26 +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + + /** + * Derives from @c unary_function or @c binary_function, or perhaps + * nothing, depending on the number of arguments provided. The + * primary template is the basis case, which derives nothing. + */ + template + struct _Maybe_unary_or_binary_function { }; + +// Ignore warnings about unary_function and binary_function. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /// Derives from @c unary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1> + : std::unary_function<_T1, _Res> { }; + + /// Derives from @c binary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> + : std::binary_function<_T1, _T2, _Res> { }; + +#pragma GCC diagnostic pop + + template + struct _Mem_fn_traits; + + template + struct _Mem_fn_traits_base + { + using __result_type = _Res; + using __maybe_type + = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>; + using __arity = integral_constant; + }; + +#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = false_type; \ + }; \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = true_type; \ + }; + +#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) + +_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) + +#if __cplusplus > 201402L +_GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) +#endif + +#undef _GLIBCXX_MEM_FN_TRAITS +#undef _GLIBCXX_MEM_FN_TRAITS2 + + /// If we have found a result_type, extract it. + template> + struct _Maybe_get_result_type + { }; + + template + struct _Maybe_get_result_type<_Functor, + __void_t> + { typedef typename _Functor::result_type result_type; }; + + /** + * Base class for any function object that has a weak result type, as + * defined in 20.8.2 [func.require] of C++11. + */ + template + struct _Weak_result_type_impl + : _Maybe_get_result_type<_Functor> + { }; + + /// Retrieve the result type for a function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a function pointer. + template + struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function pointer. + template + struct + _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + // Let _Weak_result_type_impl perform the real work. + template::value> + struct _Weak_result_type_memfun + : _Weak_result_type_impl<_Functor> + { }; + + // A pointer to member function has a weak result type. + template + struct _Weak_result_type_memfun<_MemFunPtr, true> + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; + + // A pointer to data member doesn't have a weak result type. + template + struct _Weak_result_type_memfun<_Func _Class::*, false> + { }; + + /** + * Strip top-level cv-qualifiers from the function object and let + * _Weak_result_type_memfun perform the real work. + */ + template + struct _Weak_result_type + : _Weak_result_type_memfun::type> + { }; + +#if __cplusplus <= 201703L + // Detect nested argument_type. + template> + struct _Refwrap_base_arg1 + { }; + + // Nested argument_type. + template + struct _Refwrap_base_arg1<_Tp, + __void_t> + { + typedef typename _Tp::argument_type argument_type; + }; + + // Detect nested first_argument_type and second_argument_type. + template> + struct _Refwrap_base_arg2 + { }; + + // Nested first_argument_type and second_argument_type. + template + struct _Refwrap_base_arg2<_Tp, + __void_t> + { + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; + }; + + /** + * Derives from unary_function or binary_function when it + * can. Specializations handle all of the easy cases. The primary + * template determines what to do with a class type, which may + * derive from both unary_function and binary_function. + */ + template + struct _Reference_wrapper_base + : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> + { }; + +// Ignore warnings about unary_function and binary_function. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + // - a function type (unary) + template + struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) volatile> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const volatile> + : unary_function<_T1, _Res> + { }; + + // - a function type (binary) + template + struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> + : binary_function<_T1, _T2, _Res> + { }; + + // - a function pointer type (unary) + template + struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + // - a function pointer type (binary) + template + struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template::value> + struct _Reference_wrapper_base_memfun + : _Reference_wrapper_base<_Tp> + { }; + + template + struct _Reference_wrapper_base_memfun<_MemFunPtr, true> + : _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; +#pragma GCC diagnostic pop +#endif // ! C++20 + + /// @endcond + + /** + * @brief Primary class template for reference_wrapper. + * @ingroup functors + */ + template + class reference_wrapper +#if __cplusplus <= 201703L + // In C++20 std::reference_wrapper allows T to be incomplete, + // so checking for nested types could result in ODR violations. + : public _Reference_wrapper_base_memfun::type> +#endif + { + _Tp* _M_data; + + _GLIBCXX20_CONSTEXPR + static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } + + static void _S_fun(_Tp&&) = delete; + + template> + using __not_same + = typename enable_if::value>::type; + + public: + typedef _Tp type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2993. reference_wrapper conversion from T&& + // 3041. Unnecessary decay in reference_wrapper + template, typename + = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> + _GLIBCXX20_CONSTEXPR + reference_wrapper(_Up&& __uref) + noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) + : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) + { } + + reference_wrapper(const reference_wrapper&) = default; + + reference_wrapper& + operator=(const reference_wrapper&) = default; + + _GLIBCXX20_CONSTEXPR + operator _Tp&() const noexcept + { return this->get(); } + + _GLIBCXX20_CONSTEXPR + _Tp& + get() const noexcept + { return *_M_data; } + + template + _GLIBCXX20_CONSTEXPR + typename __invoke_result<_Tp&, _Args...>::type + operator()(_Args&&... __args) const + noexcept(__is_nothrow_invocable<_Tp&, _Args...>::value) + { +#if __cplusplus > 201703L + if constexpr (is_object_v) + static_assert(sizeof(type), "type must be complete"); +#endif + return std::__invoke(get(), std::forward<_Args>(__args)...); + } + +#if __glibcxx_reference_wrapper >= 202403L // >= C++26 + // [refwrap.comparisons], comparisons + [[nodiscard]] + friend constexpr bool + operator==(reference_wrapper __x, reference_wrapper __y) + requires requires { { __x.get() == __y.get() } -> convertible_to; } + { return __x.get() == __y.get(); } + + [[nodiscard]] + friend constexpr bool + operator==(reference_wrapper __x, const _Tp& __y) + requires requires { { __x.get() == __y } -> convertible_to; } + { return __x.get() == __y; } + + [[nodiscard]] + friend constexpr bool + operator==(reference_wrapper __x, reference_wrapper __y) + requires (!is_const_v<_Tp>) + && requires { { __x.get() == __y.get() } -> convertible_to; } + { return __x.get() == __y.get(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4071. reference_wrapper comparisons are not SFINAE-friendly + + [[nodiscard]] + friend constexpr auto + operator<=>(reference_wrapper __x, reference_wrapper __y) + requires requires (const _Tp __t) { + { __t < __t } -> __detail::__boolean_testable; + } + { return __detail::__synth3way(__x.get(), __y.get()); } + + [[nodiscard]] + friend constexpr auto + operator<=>(reference_wrapper __x, const _Tp& __y) + requires requires { { __y < __y } -> __detail::__boolean_testable; } + { return __detail::__synth3way(__x.get(), __y); } + + [[nodiscard]] + friend constexpr auto + operator<=>(reference_wrapper __x, reference_wrapper __y) + requires (!is_const_v<_Tp>) && requires (const _Tp __t) { + { __t < __t } -> __detail::__boolean_testable; + } + { return __detail::__synth3way(__x.get(), __y.get()); } +#endif + }; + +#if __cpp_deduction_guides + template + reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif + + /// @relates reference_wrapper @{ + + /// Denotes a reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(_Tp& __t) noexcept + { return reference_wrapper<_Tp>(__t); } + + /// Denotes a const reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(const _Tp& __t) noexcept + { return reference_wrapper(__t); } + + template + void ref(const _Tp&&) = delete; + + template + void cref(const _Tp&&) = delete; + + /// std::ref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(reference_wrapper<_Tp> __t) noexcept + { return __t; } + + /// std::cref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(reference_wrapper<_Tp> __t) noexcept + { return { __t.get() }; } + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_REFWRAP_H diff --git a/template/sysroot/include/bits/sat_arith.h b/template/sysroot/include/bits/sat_arith.h new file mode 100644 index 0000000..7179346 --- /dev/null +++ b/template/sysroot/include/bits/sat_arith.h @@ -0,0 +1,148 @@ +// Saturation arithmetic -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/sat_arith.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{numeric} + */ + +#ifndef _GLIBCXX_SAT_ARITH_H +#define _GLIBCXX_SAT_ARITH_H 1 + +#pragma GCC system_header + +#include + +#ifdef __glibcxx_saturation_arithmetic // C++ >= 26 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Add two integers, with saturation in case of overflow. + template requires __is_standard_integer<_Tp>::value + constexpr _Tp + add_sat(_Tp __x, _Tp __y) noexcept + { + _Tp __z; + if (!__builtin_add_overflow(__x, __y, &__z)) + return __z; + if constexpr (is_unsigned_v<_Tp>) + return __gnu_cxx::__int_traits<_Tp>::__max; + else if (__x < 0) + return __gnu_cxx::__int_traits<_Tp>::__min; + else + return __gnu_cxx::__int_traits<_Tp>::__max; + } + + /// Subtract one integer from another, with saturation in case of overflow. + template requires __is_standard_integer<_Tp>::value + constexpr _Tp + sub_sat(_Tp __x, _Tp __y) noexcept + { + _Tp __z; + if (!__builtin_sub_overflow(__x, __y, &__z)) + return __z; + if constexpr (is_unsigned_v<_Tp>) + return __gnu_cxx::__int_traits<_Tp>::__min; + else if (__x < 0) + return __gnu_cxx::__int_traits<_Tp>::__min; + else + return __gnu_cxx::__int_traits<_Tp>::__max; + } + + /// Multiply two integers, with saturation in case of overflow. + template requires __is_standard_integer<_Tp>::value + constexpr _Tp + mul_sat(_Tp __x, _Tp __y) noexcept + { + _Tp __z; + if (!__builtin_mul_overflow(__x, __y, &__z)) + return __z; + if constexpr (is_unsigned_v<_Tp>) + return __gnu_cxx::__int_traits<_Tp>::__max; + else if (__x < 0 != __y < 0) + return __gnu_cxx::__int_traits<_Tp>::__min; + else + return __gnu_cxx::__int_traits<_Tp>::__max; + } + + /// Divide one integer by another, with saturation in case of overflow. + template requires __is_standard_integer<_Tp>::value + constexpr _Tp + div_sat(_Tp __x, _Tp __y) noexcept + { + __glibcxx_assert(__y != 0); + if constexpr (is_signed_v<_Tp>) + if (__x == __gnu_cxx::__int_traits<_Tp>::__min && __y == _Tp(-1)) + return __gnu_cxx::__int_traits<_Tp>::__max; + return __x / __y; + } + + /// Divide one integer by another, with saturation in case of overflow. + template + requires __is_standard_integer<_Res>::value + && __is_standard_integer<_Tp>::value + constexpr _Res + saturate_cast(_Tp __x) noexcept + { + constexpr int __digits_R = __gnu_cxx::__int_traits<_Res>::__digits; + constexpr int __digits_T = __gnu_cxx::__int_traits<_Tp>::__digits; + constexpr _Res __max_Res = __gnu_cxx::__int_traits<_Res>::__max; + + if constexpr (is_signed_v<_Res> == is_signed_v<_Tp>) + { + if constexpr (__digits_R < __digits_T) + { + constexpr _Res __min_Res = __gnu_cxx::__int_traits<_Res>::__min; + + if (__x < static_cast<_Tp>(__min_Res)) + return __min_Res; + else if (__x > static_cast<_Tp>(__max_Res)) + return __max_Res; + } + } + else if constexpr (is_signed_v<_Tp>) // Res is unsigned + { + if (__x < 0) + return 0; + else if (make_unsigned_t<_Tp>(__x) > __max_Res) + return __gnu_cxx::__int_traits<_Res>::__max; + } + else // Tp is unsigned, Res is signed + { + if (__x > make_unsigned_t<_Res>(__max_Res)) + return __max_Res; + } + return static_cast<_Res>(__x); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // __glibcxx_saturation_arithmetic +#endif /* _GLIBCXX_SAT_ARITH_H */ diff --git a/template/sysroot/include/bits/stdc++.h b/template/sysroot/include/bits/stdc++.h new file mode 100644 index 0000000..3eef20d --- /dev/null +++ b/template/sysroot/include/bits/stdc++.h @@ -0,0 +1,239 @@ +// C++ includes used for precompiling -*- C++ -*- + +// Copyright (C) 2003-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file stdc++.h + * This is an implementation file for a precompiled header. + */ + +// 17.4.1.2 Headers + +// C +#ifndef _GLIBCXX_NO_ASSERT +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#endif + +// C++ +// #include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if __cplusplus >= 201402L +#endif + +#if __cplusplus >= 201703L +#include +// #include +#include +#include +#include +#endif + +#if __cplusplus >= 202002L +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if __cplusplus > 202002L +#include +#include +#if __cpp_impl_coroutine +# include +#endif +#endif + +#if _GLIBCXX_HOSTED +// C +#ifndef _GLIBCXX_NO_ASSERT +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +// C++ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if __cplusplus >= 201402L +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +// #include +#include +#include +#include +#include +#endif + +#if __cplusplus >= 202002L +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if __cplusplus > 202002L +#include +#include +#include +#include +#if __has_include() +# include +#endif +#include +#include +#endif + +#if __cplusplus > 202302L +#include +#endif + +#endif // HOSTED diff --git a/template/sysroot/include/bits/stdtr1c++.h b/template/sysroot/include/bits/stdtr1c++.h new file mode 100644 index 0000000..19004a6 --- /dev/null +++ b/template/sysroot/include/bits/stdtr1c++.h @@ -0,0 +1,53 @@ +// C++ includes used for precompiling TR1 -*- C++ -*- + +// Copyright (C) 2006-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file stdtr1c++.h + * This is an implementation file for a precompiled header. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/template/sysroot/include/bits/stl_algo.h b/template/sysroot/include/bits/stl_algo.h new file mode 100644 index 0000000..1a996aa --- /dev/null +++ b/template/sysroot/include/bits/stl_algo.h @@ -0,0 +1,5854 @@ +// Algorithm implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGO_H +#define _STL_ALGO_H 1 + +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#endif + +#if _GLIBCXX_HOSTED +# include // for _Temporary_buffer +# if (__cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED) +# include // for rand +# endif +#endif + +// See concept_check.h for the __glibcxx_*_requires macros. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Swaps the median value of *__a, *__b and *__c under __comp to *__result + template + _GLIBCXX20_CONSTEXPR + void + __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, + _Iterator __c, _Compare __comp) + { + if (__comp(__a, __b)) + { + if (__comp(__b, __c)) + std::iter_swap(__result, __b); + else if (__comp(__a, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __a); + } + else if (__comp(__a, __c)) + std::iter_swap(__result, __a); + else if (__comp(__b, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __b); + } + + /// Provided for stable_partition to use. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__negate(__pred), + std::__iterator_category(__first)); + } + + /// Like find_if_not(), but uses and updates a count of the + /// remaining range length instead of comparing against an end + /// iterator. + template + _GLIBCXX20_CONSTEXPR + _InputIterator + __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) + { + for (; __len; --__len, (void) ++__first) + if (!__pred(__first)) + break; + return __first; + } + + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + // for_each + // find + // find_if + // find_first_of + // adjacent_find + // count + // count_if + // search + // search_n + + /** + * This is an helper function for search_n overloaded for forward iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n_aux(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::forward_iterator_tag) + { + __first = std::__find_if(__first, __last, __unary_pred); + while (__first != __last) + { + typename iterator_traits<_ForwardIterator>::difference_type + __n = __count; + _ForwardIterator __i = __first; + ++__i; + while (__i != __last && __n != 1 && __unary_pred(__i)) + { + ++__i; + --__n; + } + if (__n == 1) + return __first; + if (__i == __last) + return __last; + __first = std::__find_if(++__i, __last, __unary_pred); + } + return __last; + } + + /** + * This is an helper function for search_n overloaded for random access + * iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIter + __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::random_access_iterator_tag) + { + typedef typename std::iterator_traits<_RandomAccessIter>::difference_type + _DistanceType; + + _DistanceType __tailSize = __last - __first; + _DistanceType __remainder = __count; + + while (__remainder <= __tailSize) // the main loop... + { + __first += __remainder; + __tailSize -= __remainder; + // __first here is always pointing to one past the last element of + // next possible match. + _RandomAccessIter __backTrack = __first; + while (__unary_pred(--__backTrack)) + { + if (--__remainder == 0) + return (__first - __count); // Success + } + __remainder = __count + 1 - (__first - __backTrack); + } + return __last; // Failure + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, + _UnaryPredicate __unary_pred) + { + if (__count <= 0) + return __first; + + if (__count == 1) + return std::__find_if(__first, __last, __unary_pred); + + return std::__search_n_aux(__first, __last, __count, __unary_pred, + std::__iterator_category(__first)); + } + + // find_end for forward iterators. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + forward_iterator_tag, forward_iterator_tag, + _BinaryPredicate __comp) + { + if (__first2 == __last2) + return __last1; + + _ForwardIterator1 __result = __last1; + while (1) + { + _ForwardIterator1 __new_result + = std::__search(__first1, __last1, __first2, __last2, __comp); + if (__new_result == __last1) + return __result; + else + { + __result = __new_result; + __first1 = __new_result; + ++__first1; + } + } + } + + // find_end for bidirectional iterators (much faster). + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator1 + __find_end(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator1>) + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator2>) + + typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1; + typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2; + + _RevIterator1 __rlast1(__first1); + _RevIterator2 __rlast2(__first2); + _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1, + _RevIterator2(__last2), __rlast2, + __comp); + + if (__rresult == __rlast1) + return __last1; + else + { + _BidirectionalIterator1 __result = __rresult.base(); + std::advance(__result, -std::distance(__first2, __last2)); + return __result; + } + } + + /** + * @brief Find last matching subsequence in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @return The last iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == + * @p *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the __first + * element of the sub-sequence, or @p __last1 if the sub-sequence + * is not found. The sub-sequence will be the last such + * subsequence contained in [__first1,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find last matching subsequence in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @param __comp The predicate to use. + * @return The last iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c + * predicate(*(i+N), @p (__first2+N)) is true for each @c N in the + * range @p [0,__last2-__first2), or @p __last1 if no such iterator + * exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) using comp as a predicate and returns an + * iterator to the first element of the sub-sequence, or @p __last1 + * if the sub-sequence is not found. The sub-sequence will be the + * last such subsequence contained in [__first,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201103L + /** + * @brief Checks that a predicate is true for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is true for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == std::find_if_not(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is false for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is false for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is true for at least one element + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if an element exists in the range @p + * [__first,__last) such that @p __pred is true, and false + * otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return !std::none_of(__first, __last, __pred); } + + /** + * @brief Find the first element in a sequence for which a + * predicate is false. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is false, or @p __last if no such iterator exists. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if_not(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Checks whether the sequence is partitioned. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the range @p [__first,__last) is partioned by @p __pred, + * i.e. if all elements that satisfy @p __pred appear before those that + * do not. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_partitioned(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + __first = std::find_if_not(__first, __last, __pred); + if (__first == __last) + return true; + ++__first; + return std::none_of(__first, __last, __pred); + } + + /** + * @brief Find the partition point of a partitioned range. + * @ingroup mutating_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __pred A predicate. + * @return An iterator @p mid such that @p all_of(__first, mid, __pred) + * and @p none_of(mid, __last, __pred) are both true. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + _ForwardIterator + partition_point(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + + // A specific debug-mode test will be necessary... + __glibcxx_requires_valid_range(__first, __last); + + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__pred(*__middle)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } +#endif + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + /** + * @brief Copy a sequence, removing elements of a given value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) not equal + * to @p __value to the range beginning at @p __result. + * remove_copy() is stable, so the relative order of elements that + * are copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Copy a sequence, removing elements for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns false to the range beginning at @p __result. + * + * remove_copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + +#if __cplusplus >= 201103L + /** + * @brief Copy the elements of a sequence for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p __result. + * + * copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n(_InputIterator __first, _Size __n, + _OutputIterator __result, input_iterator_tag) + { + return std::__niter_wrap(__result, + __copy_n_a(__first, __n, + std::__niter_base(__result), true)); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __copy_n(_RandomAccessIterator __first, _Size __n, + _OutputIterator __result, random_access_iterator_tag) + { return std::copy(__first, __first + __n, __result); } + + /** + * @brief Copies the range [first,first+n) into [result,result+n). + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return result+n. + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + + const auto __n2 = std::__size_to_integer(__n); + if (__n2 <= 0) + return __result; + + __glibcxx_requires_can_increment(__first, __n2); + __glibcxx_requires_can_increment(__result, __n2); + + return std::__copy_n(__first, __n2, __result, + std::__iterator_category(__first)); + } + + /** + * @brief Copy the elements of a sequence to separate output sequences + * depending on the truth value of a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __out_true An output iterator. + * @param __out_false An output iterator. + * @param __pred A predicate. + * @return A pair designating the ends of the resulting sequences. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p out_true + * and each element for which @p __pred returns false to @p __out_false. + */ + template + _GLIBCXX20_CONSTEXPR + pair<_OutputIterator1, _OutputIterator2> + partition_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator1 __out_true, _OutputIterator2 __out_false, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); + } +#endif // C++11 + + /** + * @brief Remove elements from a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * All elements equal to @p __value are removed from the range + * @p [__first,__last). + * + * remove() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Remove elements from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * All elements for which @p __pred returns true are removed from the range + * @p [__first,__last). + * + * remove_if() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + if (__first == __last) + return __last; + _ForwardIterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(__first, __next)) + return __first; + __first = __next; + } + return __last; + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // Skip the beginning, if already unique. + __first = std::__adjacent_find(__first, __last, __binary_pred); + if (__first == __last) + return __last; + + // Do the real copy work. + _ForwardIterator __dest = __first; + ++__first; + while (++__first != __last) + if (!__binary_pred(__dest, __first)) + *++__dest = _GLIBCXX_MOVE(*__first); + return ++__dest; + } + + /** + * @brief Remove consecutive duplicate values from a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values that compare equal. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Remove consecutive values from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values for which @p __binary_pred returns true. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for forward iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + forward_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + + _ForwardIterator __next = __first; + *__result = *__first; + while (++__next != __last) + if (!__binary_pred(__first, __next)) + { + __first = __next; + *++__result = *__first; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + + typename iterator_traits<_InputIterator>::value_type __value = *__first; + __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) + __rebound_pred + = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); + *__result = __value; + while (++__first != __last) + if (!__rebound_pred(__first, __value)) + { + __value = *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and forward iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, forward_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + *__result = *__first; + while (++__first != __last) + if (!__binary_pred(__result, __first)) + *++__result = *__first; + return ++__result; + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for bidirectional iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + while (true) + if (__first == __last || __first == --__last) + return; + else + { + std::iter_swap(__first, __last); + ++__first; + } + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for random access iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + if (__first == __last) + return; + --__last; + while (__first < __last) + { + std::iter_swap(__first, __last); + ++__first; + --__last; + } + } + + /** + * @brief Reverse a sequence. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @return reverse() returns no value. + * + * Reverses the order of the elements in the range @p [__first,__last), + * so that the first element becomes the last etc. + * For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse() + * swaps @p *(__first+i) and @p *(__last-(i+1)) + */ + template + _GLIBCXX20_CONSTEXPR + inline void + reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_requires_valid_range(__first, __last); + std::__reverse(__first, __last, std::__iterator_category(__first)); + } + + /** + * @brief Copy a sequence, reversing its elements. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements in the range @p [__first,__last) to the + * range @p [__result,__result+(__last-__first)) such that the + * order of the elements is reversed. For every @c i such that @p + * 0<=i<=(__last-__first), @p reverse_copy() performs the + * assignment @p *(__result+(__last-__first)-1-i) = *(__first+i). + * The ranges @p [__first,__last) and @p + * [__result,__result+(__last-__first)) must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + while (__first != __last) + { + --__last; + *__result = *__last; + ++__result; + } + return __result; + } + + /** + * This is a helper function for the rotate algorithm specialized on RAIs. + * It returns the greatest common divisor of two integer values. + */ + template + _GLIBCXX20_CONSTEXPR + _EuclideanRingElement + __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) + { + while (__n != 0) + { + _EuclideanRingElement __t = __m % __n; + __m = __n; + __n = __t; + } + return __m; + } + +_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __rotate(_ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + forward_iterator_tag) + { + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + _ForwardIterator __first2 = __middle; + do + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } + while (__first2 != __last); + + _ForwardIterator __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return __ret; + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __rotate(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + + while (__first != __middle && __middle != __last) + { + std::iter_swap(__first, --__last); + ++__first; + } + + if (__first == __middle) + { + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + return __last; + } + else + { + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + return __first; + } + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __rotate(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + +#if __cplusplus >= 201103L + typedef typename make_unsigned<_Distance>::type _UDistance; +#else + typedef _Distance _UDistance; +#endif + + _Distance __n = __last - __first; + _Distance __k = __middle - __first; + + if (__k == __n - __k) + { + std::swap_ranges(__first, __middle, __middle); + return __middle; + } + + _RandomAccessIterator __p = __first; + _RandomAccessIterator __ret = __first + (__last - __middle); + + for (;;) + { + if (__k < __n - __k) + { + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*__p); + _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); + *(__p + __n - 1) = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + std::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n = static_cast<_UDistance>(__n) % static_cast<_UDistance>(__k); + if (__n == 0) + return __ret; + std::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); + _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); + *__p = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __n; + __p = __q - __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + std::iter_swap(__p, __q); + } + __n = static_cast<_UDistance>(__n) % static_cast<_UDistance>(__k); + if (__n == 0) + return __ret; + std::swap(__n, __k); + } + } + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 488. rotate throws away useful information + /** + * @brief Rotate the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @return first + (last - middle). + * + * Rotates the elements of the range @p [__first,__last) by + * @p (__middle - __first) positions so that the element at @p __middle + * is moved to @p __first, the element at @p __middle+1 is moved to + * @p __first+1 and so on for each element in the range + * @p [__first,__last). + * + * This effectively swaps the ranges @p [__first,__middle) and + * @p [__middle,__last). + * + * Performs + * @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + rotate(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::__rotate(__first, __middle, __last, + std::__iterator_category(__first)); + } + +_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) + + /** + * @brief Copy a sequence, rotating its elements. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements of the range @p [__first,__last) to the + * range beginning at @result, rotating the copied elements by + * @p (__middle-__first) positions so that the element at @p __middle + * is moved to @p __result, the element at @p __middle+1 is moved + * to @p __result+1 and so on for each element in the range @p + * [__first,__last). + * + * Performs + * @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::copy(__first, __middle, + std::copy(__middle, __last, __result)); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, forward_iterator_tag) + { + if (__first == __last) + return __first; + + while (__pred(*__first)) + if (++__first == __last) + return __first; + + _ForwardIterator __next = __first; + + while (++__next != __last) + if (__pred(*__next)) + { + std::iter_swap(__first, __next); + ++__first; + } + + return __first; + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, + _Predicate __pred, bidirectional_iterator_tag) + { + while (true) + { + while (true) + if (__first == __last) + return __first; + else if (__pred(*__first)) + ++__first; + else + break; + --__last; + while (true) + if (__first == __last) + return __first; + else if (!bool(__pred(*__last))) + --__last; + else + break; + std::iter_swap(__first, __last); + ++__first; + } + } + +#if _GLIBCXX_HOSTED + // partition + + /// This is a helper function... + /// Requires __first != __last and !__pred(__first) + /// and __len == distance(__first, __last). + /// + /// !__pred(__first) allows us to guarantee that we don't + /// move-assign an element onto itself. + template + _ForwardIterator + __stable_partition_adaptive(_ForwardIterator __first, + _ForwardIterator __last, + _Predicate __pred, _Distance __len, + _Pointer __buffer, + _Distance __buffer_size) + { + if (__len == 1) + return __first; + + if (__len <= __buffer_size) + { + _ForwardIterator __result1 = __first; + _Pointer __result2 = __buffer; + + // The precondition guarantees that !__pred(__first), so + // move that element to the buffer before starting the loop. + // This ensures that we only call __pred once per element. + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + ++__first; + for (; __first != __last; ++__first) + if (__pred(__first)) + { + *__result1 = _GLIBCXX_MOVE(*__first); + ++__result1; + } + else + { + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + } + + _GLIBCXX_MOVE3(__buffer, __result2, __result1); + return __result1; + } + + _ForwardIterator __middle = __first; + std::advance(__middle, __len / 2); + _ForwardIterator __left_split = + std::__stable_partition_adaptive(__first, __middle, __pred, + __len / 2, __buffer, + __buffer_size); + + // Advance past true-predicate values to satisfy this + // function's preconditions. + _Distance __right_len = __len - __len / 2; + _ForwardIterator __right_split = + std::__find_if_not_n(__middle, __right_len, __pred); + + if (__right_len) + __right_split = + std::__stable_partition_adaptive(__right_split, __last, __pred, + __right_len, + __buffer, __buffer_size); + + return std::rotate(__left_split, __middle, __right_split); + } + + template + _ForwardIterator + __stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if_not(__first, __last, __pred); + + if (__first == __last) + return __first; + + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _Temporary_buffer<_ForwardIterator, _ValueType> + __buf(__first, std::distance(__first, __last)); + return + std::__stable_partition_adaptive(__first, __last, __pred, + _DistanceType(__buf.requested_size()), + __buf.begin(), + _DistanceType(__buf.size())); + } + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence, preserving relative ordering. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator @p middle such that @p __pred(i) is true for each + * iterator @p i in the range @p [first,middle) and false for each @p i + * in the range @p [middle,last). + * + * Performs the same function as @p partition() with the additional + * guarantee that the relative ordering of elements in each group is + * preserved, so any two elements @p x and @p y in the range + * @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same + * relative ordering after calling @p stable_partition(). + */ + template + inline _ForwardIterator + stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__stable_partition(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } +#endif // HOSTED + + /// @cond undocumented + + /// This is a helper function for the sort routines. + template + _GLIBCXX20_CONSTEXPR + void + __heap_select(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, _Compare __comp) + { + std::__make_heap(__first, __middle, __comp); + for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) + if (__comp(__i, __first)) + std::__pop_heap(__first, __middle, __i, __comp); + } + + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef iterator_traits<_RandomAccessIterator> _RItTraits; + typedef typename _RItTraits::difference_type _DistanceType; + + if (__result_first == __result_last) + return __result_last; + _RandomAccessIterator __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + std::__make_heap(__result_first, __result_real_last, __comp); + while (__first != __last) + { + if (__comp(__first, __result_first)) + std::__adjust_heap(__result_first, _DistanceType(0), + _DistanceType(__result_real_last + - __result_first), + _InputValueType(*__first), __comp); + ++__first; + } + std::__sort_heap(__result_first, __result_real_last, __comp); + return __result_real_last; + } + + /// @endcond + + /** + * @brief Copy the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest `N` values from the range + * `[__first, __last)` to the range beginning at `__result_first`, where + * the number of elements to be copied, `N`, is the smaller of + * `(__last - __first)` and `(__result_last - __result_first)`. + * After the sort if `i` and `j` are iterators in the range + * `[__result_first,__result_first + N)` such that `i` precedes `j` then + * `*j < *i` is false. + * The value returned is `__result_first + N`. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanOpConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Copy the smallest elements of a sequence using a predicate for + * comparison. + * @ingroup sorting_algorithms + * @param __first An input iterator. + * @param __last Another input iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @param __comp A comparison functor. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest `N` values from the range + * `[__first, __last)` to the range beginning at `result_first`, where + * the number of elements to be copied, `N`, is the smaller of + * `(__last - __first)` and `(__result_last - __result_first)`. + * After the sort if `i` and `j` are iterators in the range + * `[__result_first, __result_first + N)` such that `i` precedes `j` then + * `__comp(*j, *i)` is false. + * The value returned is `__result_first + N`. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _InputValueType, _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _OutputValueType, _OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /// @cond undocumented + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __unguarded_linear_insert(_RandomAccessIterator __last, + _Compare __comp) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__last); + _RandomAccessIterator __next = __last; + --__next; + while (__comp(__val, __next)) + { + *__last = _GLIBCXX_MOVE(*__next); + __last = __next; + --__next; + } + *__last = _GLIBCXX_MOVE(__val); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__first == __last) return; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + if (__comp(__i, __first)) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__i); + _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); + *__first = _GLIBCXX_MOVE(__val); + } + else + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + inline void + __unguarded_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + for (_RandomAccessIterator __i = __first; __i != __last; ++__i) + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @doctodo + * This controls some aspect of the sort routines. + */ + enum { _S_threshold = 16 }; + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __final_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first > int(_S_threshold)) + { + std::__insertion_sort(__first, __first + int(_S_threshold), __comp); + std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, + __comp); + } + else + std::__insertion_sort(__first, __last, __comp); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __unguarded_partition(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __pivot, _Compare __comp) + { + while (true) + { + while (__comp(__first, __pivot)) + ++__first; + --__last; + while (__comp(__pivot, __last)) + --__last; + if (!(__first < __last)) + return __first; + std::iter_swap(__first, __last); + ++__first; + } + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + __unguarded_partition_pivot(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + _RandomAccessIterator __mid = __first + (__last - __first) / 2; + std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, + __comp); + return std::__unguarded_partition(__first + 1, __last, __first, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + std::__heap_select(__first, __middle, __last, __comp); + std::__sort_heap(__first, __middle, __comp); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __introsort_loop(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __depth_limit, _Compare __comp) + { + while (__last - __first > int(_S_threshold)) + { + if (__depth_limit == 0) + { + std::__partial_sort(__first, __last, __last, __comp); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + std::__introsort_loop(__cut, __last, __depth_limit, __comp); + __last = __cut; + } + } + + // sort + + template + _GLIBCXX20_CONSTEXPR + inline void + __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + if (__first != __last) + { + std::__introsort_loop(__first, __last, + std::__lg(__last - __first) * 2, + __comp); + std::__final_insertion_sort(__first, __last, __comp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Size __depth_limit, + _Compare __comp) + { + while (__last - __first > 3) + { + if (__depth_limit == 0) + { + std::__heap_select(__first, __nth + 1, __last, __comp); + // Place the nth largest element in its final position. + std::iter_swap(__first, __nth); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + std::__insertion_sort(__first, __last, __comp); + } + + /// @endcond + + // nth_element + + // lower_bound moved to stl_algobase.h + + /** + * @brief Finds the first position in which `__val` could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator to the start of a sorted range. + * @param __last A past-the-end iterator for the sorted range. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element _not less than_ + * `__val`, or `end()` if every element is less than `__val`. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__val, __middle)) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, + _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp_it_val(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (__comp_val_it(__val, __middle)) + __len = __half; + else + { + _ForwardIterator __left + = std::__lower_bound(__first, __middle, __val, __comp_it_val); + std::advance(__first, __len); + _ForwardIterator __right + = std::__upper_bound(++__middle, __first, __val, __comp_val_it); + return pair<_ForwardIterator, _ForwardIterator>(__left, __right); + } + } + return pair<_ForwardIterator, _ForwardIterator>(__first, __first); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val), + * upper_bound(__first, __last, __val)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val(), + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val, __comp), + * upper_bound(__first, __last, __val, __comp)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp), + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return True if @p __val (or its equivalent) is in [@p + * __first,@p __last ]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + return __i != __last && !(__val < *__i); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return True if @p __val (or its equivalent) is in @p [__first,__last]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + return __i != __last && !bool(__comp(__val, *__i)); + } + + // merge + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + _GLIBCXX_MOVE3(__first1, __last1, __result); + } + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + _BidirectionalIterator3 __result, + _Compare __comp) + { + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + + --__last1; + --__last2; + while (true) + { + if (__comp(__last2, __last1)) + { + *--__result = _GLIBCXX_MOVE(*__last1); + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + return; + } + --__last1; + } + else + { + *--__result = _GLIBCXX_MOVE(*__last2); + if (__first2 == __last2) + return; + --__last2; + } + } + } + + /// This is a helper function for the merge routines. + template + _BidirectionalIterator1 + __rotate_adaptive(_BidirectionalIterator1 __first, + _BidirectionalIterator1 __middle, + _BidirectionalIterator1 __last, + _Distance __len1, _Distance __len2, + _BidirectionalIterator2 __buffer, + _Distance __buffer_size) + { + _BidirectionalIterator2 __buffer_end; + if (__len1 > __len2 && __len2 <= __buffer_size) + { + if (__len2) + { + __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); + return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); + } + else + return __first; + } + else if (__len1 <= __buffer_size) + { + if (__len1) + { + __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_MOVE3(__middle, __last, __first); + return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); + } + else + return __last; + } + else + return std::rotate(__first, __middle, __last); + } + + /// This is a helper function for the merge routines. + template + void + __merge_adaptive(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Compare __comp) + { + if (__len1 <= __len2) + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first, __comp); + } + else + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + std::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last, __comp); + } + } + + template + void + __merge_adaptive_resize(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + if (__len1 <= __buffer_size || __len2 <= __buffer_size) + std::__merge_adaptive(__first, __middle, __last, + __len1, __len2, __buffer, __comp); + else + { + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::__rotate_adaptive(__first_cut, __middle, __second_cut, + _Distance(__len1 - __len11), __len22, + __buffer, __buffer_size); + std::__merge_adaptive_resize(__first, __first_cut, __new_middle, + __len11, __len22, + __buffer, __buffer_size, __comp); + std::__merge_adaptive_resize(__new_middle, __second_cut, __last, + _Distance(__len1 - __len11), + _Distance(__len2 - __len22), + __buffer, __buffer_size, __comp); + } + } + + /// This is a helper function for the merge routines. + template + void + __merge_without_buffer(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Compare __comp) + { + if (__len1 == 0 || __len2 == 0) + return; + + if (__len1 + __len2 == 2) + { + if (__comp(__middle, __first)) + std::iter_swap(__first, __middle); + return; + } + + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::rotate(__first_cut, __middle, __second_cut); + std::__merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22, __comp); + std::__merge_without_buffer(__new_middle, __second_cut, __last, + __len1 - __len11, __len2 - __len22, __comp); + } + + template + void + __inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_BidirectionalIterator>::value_type + _ValueType; + typedef typename iterator_traits<_BidirectionalIterator>::difference_type + _DistanceType; + + if (__first == __middle || __middle == __last) + return; + + const _DistanceType __len1 = std::distance(__first, __middle); + const _DistanceType __len2 = std::distance(__middle, __last); + +#if _GLIBCXX_HOSTED + typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; + // __merge_adaptive will use a buffer for the smaller of + // [first,middle) and [middle,last). + _TmpBuf __buf(__first, std::min(__len1, __len2)); + + if (__builtin_expect(__buf.size() == __buf.requested_size(), true)) + std::__merge_adaptive + (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp); + else if (__builtin_expect(__buf.begin() == 0, false)) + std::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp); + else + std::__merge_adaptive_resize + (__first, __middle, __last, __len1, __len2, __buf.begin(), + _DistanceType(__buf.size()), __comp); +#else + std::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp); +#endif + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [__middle,__last), and puts the result in [__first,__last). The + * output will be sorted. The sort is @e stable, that is, for + * equivalent elements in the two ranges, elements from the first + * range will always come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted(__first, __middle); + __glibcxx_requires_sorted(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A functor to use for comparisons. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [middle,last), and puts the result in [__first,__last). The output will + * be sorted. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted_pred(__first, __middle, __comp); + __glibcxx_requires_sorted_pred(__middle, __last, __comp); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + + /// This is a helper function for the __merge_sort_loop routines. + template + _OutputIterator + __move_merge(_InputIterator __first1, _InputIterator __last1, + _InputIterator __first2, _InputIterator __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + return _GLIBCXX_MOVE3(__first2, __last2, + _GLIBCXX_MOVE3(__first1, __last1, + __result)); + } + + template + void + __merge_sort_loop(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, _Distance __step_size, + _Compare __comp) + { + const _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) + { + __result = std::__move_merge(__first, __first + __step_size, + __first + __step_size, + __first + __two_step, + __result, __comp); + __first += __two_step; + } + __step_size = std::min(_Distance(__last - __first), __step_size); + + std::__move_merge(__first, __first + __step_size, + __first + __step_size, __last, __result, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __chunk_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Distance __chunk_size, _Compare __comp) + { + while (__last - __first >= __chunk_size) + { + std::__insertion_sort(__first, __first + __chunk_size, __comp); + __first += __chunk_size; + } + std::__insertion_sort(__first, __last, __comp); + } + + enum { _S_chunk_size = 7 }; + + template + void + __merge_sort_with_buffer(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + + const _Distance __len = __last - __first; + const _Pointer __buffer_last = __buffer + __len; + + _Distance __step_size = _S_chunk_size; + std::__chunk_insertion_sort(__first, __last, __step_size, __comp); + + while (__step_size < __len) + { + std::__merge_sort_loop(__first, __last, __buffer, + __step_size, __comp); + __step_size *= 2; + std::__merge_sort_loop(__buffer, __buffer_last, __first, + __step_size, __comp); + __step_size *= 2; + } + } + + template + void + __stable_sort_adaptive(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Pointer __buffer, _Compare __comp) + { + std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); + std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); + + std::__merge_adaptive(__first, __middle, __last, + __middle - __first, __last - __middle, + __buffer, __comp); + } + + template + void + __stable_sort_adaptive_resize(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + const _Distance __len = (__last - __first + 1) / 2; + const _RandomAccessIterator __middle = __first + __len; + if (__len > __buffer_size) + { + std::__stable_sort_adaptive_resize(__first, __middle, __buffer, + __buffer_size, __comp); + std::__stable_sort_adaptive_resize(__middle, __last, __buffer, + __buffer_size, __comp); + std::__merge_adaptive_resize(__first, __middle, __last, + _Distance(__middle - __first), + _Distance(__last - __middle), + __buffer, __buffer_size, + __comp); + } + else + std::__stable_sort_adaptive(__first, __middle, __last, + __buffer, __comp); + } + + /// This is a helper function for the stable sorting routines. + template + void + __inplace_stable_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first < 15) + { + std::__insertion_sort(__first, __last, __comp); + return; + } + _RandomAccessIterator __middle = __first + (__last - __first) / 2; + std::__inplace_stable_sort(__first, __middle, __comp); + std::__inplace_stable_sort(__middle, __last, __comp); + std::__merge_without_buffer(__first, __middle, __last, + __middle - __first, + __last - __middle, + __comp); + } + + // stable_sort + + // Set algorithms: includes, set_union, set_intersection, set_difference, + // set_symmetric_difference. All of these algorithms have the precondition + // that their input ranges are sorted and the postcondition that their output + // ranges are sorted. + + template + _GLIBCXX20_CONSTEXPR + bool + __includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + return false; + if (!__comp(__first1, __first2)) + ++__first2; + ++__first1; + } + + return __first2 == __last2; + } + + /** + * @brief Determines whether all elements of a sequence exists in a range. + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @return True if each element in [__first2,__last2) is contained in order + * within [__first1,__last1). False otherwise. + * @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1). + * The iterators over each range only move forward, so this is a + * linear algorithm. If an element in [__first2,__last2) is not + * found before the search iterator reaches @p __last2, false is + * returned. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines whether all elements of a sequence exists in a range + * using comparison. + * @ingroup set_algorithms + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @param __comp Comparison function to use. + * @return True if each element in [__first2,__last2) is contained + * in order within [__first1,__last1) according to comp. False + * otherwise. @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1), + * using comp to decide. The iterators over each range only move + * forward, so this is a linear algorithm. If an element in + * [__first2,__last2) is not found before the search iterator + * reaches @p __last2, false is returned. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // nth_element + // merge + // set_difference + // set_intersection + // set_union + // stable_sort + // set_symmetric_difference + // min_element + // max_element + + template + _GLIBCXX20_CONSTEXPR + bool + __next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__i, __ii)) + { + _BidirectionalIterator __j = __last; + while (!__comp(__i, --__j)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the next @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the next one of this set. + * Returns true if there are more sequences to generate. If the sequence + * is the largest of the set, the smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the next @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the next one of this set. Returns true if there are more + * sequences to generate. If the sequence is the largest of the set, the + * smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + bool + __prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__ii, __i)) + { + _BidirectionalIterator __j = __last; + while (!__comp(--__j, __i)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the previous @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the previous one of this + * set. Returns true if there are more sequences to generate. If the + * sequence is the smallest of the set, the largest is generated and false + * returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the previous @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the previous one of this set. Returns true if there are + * more sequences to generate. If the sequence is the smallest of the set, + * the largest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // replace + // replace_if + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + for (; __first != __last; ++__first, (void)++__result) + if (__pred(__first)) + *__result = __new_value; + else + *__result = *__first; + return __result; + } + + /** + * @brief Copy a sequence, replacing each element of one value with another + * value. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p result+(last-first). + * + * Copies each element in the input range @p [__first,__last) to the + * output range @p [__result,__result+(__last-__first)) replacing elements + * equal to @p __old_value with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__old_value), + __new_value); + } + + /** + * @brief Copy a sequence, replacing each value for which a predicate + * returns true with another value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p __result+(__last-__first). + * + * Copies each element in the range @p [__first,__last) to the range + * @p [__result,__result+(__last-__first)) replacing elements for which + * @p __pred returns true with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred), + __new_value); + } + +#if __cplusplus >= 201103L + /** + * @brief Determines whether the elements of a sequence are sorted. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last) + { return std::is_sorted_until(__first, __last) == __last; } + + /** + * @brief Determines whether the elements of a sequence are sorted + * according to a comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { return std::is_sorted_until(__first, __last, __comp) == __last; } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __last; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (__comp(__next, __first)) + return __next; + return __next; + } + + /** + * @brief Determines the end of a sorted sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines the end of a sorted sequence using comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + + return __b < __a ? pair(__b, __a) + : pair(__a, __b); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor @endlink. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + return __comp(__b, __a) ? pair(__b, __a) + : pair(__a, __b); + } + + template + _GLIBCXX14_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + _ForwardIterator __next = __first; + if (__first == __last + || ++__next == __last) + return std::make_pair(__first, __first); + + _ForwardIterator __min{}, __max{}; + if (__comp(__next, __first)) + { + __min = __next; + __max = __first; + } + else + { + __min = __first; + __max = __next; + } + + __first = __next; + ++__first; + + while (__first != __last) + { + __next = __first; + if (++__next == __last) + { + if (__comp(__first, __min)) + __min = __first; + else if (!__comp(__first, __max)) + __max = __first; + break; + } + + if (__comp(__next, __first)) + { + if (__comp(__next, __min)) + __min = __next; + if (!__comp(__first, __max)) + __max = __first; + } + else + { + if (__comp(__first, __min)) + __min = __first; + if (!__comp(__next, __max)) + __max = __next; + } + + __first = __next; + ++__first; + } + + return std::make_pair(__min, __max); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l) + { + __glibcxx_requires_irreflexive(__l.begin(), __l.end()); + pair __p = + std::__minmax_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_less_iter()); + return std::make_pair(*__p.first, *__p.second); + } + + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l, _Compare __comp) + { + __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); + pair __p = + std::__minmax_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::make_pair(*__p.first, *__p.second); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in + * the range [__first2, __first2 + (__last1 - __first1)), + * beginning with ForwardIterator2 begin, such that + * equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } + +#if __cplusplus > 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + using _Cat1 + = typename iterator_traits<_ForwardIterator1>::iterator_category; + using _Cat2 + = typename iterator_traits<_ForwardIterator2>::iterator_category; + using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; + using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; + constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); + if (__ra_iters) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__ra_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches + || std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutaion of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, begin) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return + std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } +#endif // C++14 + +#ifdef __glibcxx_clamp // C++ >= 17 + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @retval `__lo` if `__val < __lo` + * @retval `__hi` if `__hi < __val` + * @retval `__val` otherwise. + * @pre `_Tp` is LessThanComparable and `(__hi < __lo)` is false. + */ + template + [[nodiscard]] constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) + { + __glibcxx_assert(!(__hi < __lo)); + return std::min(std::max(__val, __lo), __hi); + } + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @param __comp A comparison functor. + * @retval `__lo` if `__comp(__val, __lo)` + * @retval `__hi` if `__comp(__hi, __val)` + * @retval `__val` otherwise. + * @pre `__comp(__hi, __lo)` is false. + */ + template + [[nodiscard]] constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) + { + __glibcxx_assert(!__comp(__hi, __lo)); + return std::min(std::max(__val, __lo, __comp), __hi, __comp); + } +#endif // __glibcxx_clamp + + /** + * @brief Generate two uniformly distributed integers using a + * single distribution invocation. + * @param __b0 The upper bound for the first integer. + * @param __b1 The upper bound for the second integer. + * @param __g A UniformRandomBitGenerator. + * @return A pair (i, j) with i and j uniformly distributed + * over [0, __b0) and [0, __b1), respectively. + * + * Requires: __b0 * __b1 <= __g.max() - __g.min(). + * + * Using uniform_int_distribution with a range that is very + * small relative to the range of the generator ends up wasting + * potentially expensively generated randomness, since + * uniform_int_distribution does not store leftover randomness + * between invocations. + * + * If we know we want two integers in ranges that are sufficiently + * small, we can compose the ranges, use a single distribution + * invocation, and significantly reduce the waste. + */ + template + pair<_IntType, _IntType> + __gen_two_uniform_ints(_IntType __b0, _IntType __b1, + _UniformRandomBitGenerator&& __g) + { + _IntType __x + = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); + return std::make_pair(__x / __b1, __x % __b1); + } + + /** + * @brief Shuffle the elements of a sequence using a uniform random + * number generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __g A UniformRandomNumberGenerator (26.5.1.3). + * @return Nothing. + * + * Reorders the elements in the range @p [__first,__last) using @p __g to + * provide random numbers. + */ + template + void + shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, + _UniformRandomNumberGenerator&& __g) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + typedef typename std::make_unsigned<_DistanceType>::type __ud_type; + typedef typename std::uniform_int_distribution<__ud_type> __distr_type; + typedef typename __distr_type::param_type __p_type; + + typedef typename remove_reference<_UniformRandomNumberGenerator>::type + _Gen; + typedef typename common_type::type + __uc_type; + + const __uc_type __urngrange = __g.max() - __g.min(); + const __uc_type __urange = __uc_type(__last - __first); + + if (__urngrange / __urange >= __urange) + // I.e. (__urngrange >= __urange * __urange) but without wrap issues. + { + _RandomAccessIterator __i = __first + 1; + + // Since we know the range isn't empty, an even number of elements + // means an uneven number of elements /to swap/, in which case we + // do the first one up front: + + if ((__urange % 2) == 0) + { + __distr_type __d{0, 1}; + std::iter_swap(__i++, __first + __d(__g)); + } + + // Now we know that __last - __i is even, so we do the rest in pairs, + // using a single distribution invocation to produce swap positions + // for two successive elements at a time: + + while (__i != __last) + { + const __uc_type __swap_range = __uc_type(__i - __first) + 1; + + const pair<__uc_type, __uc_type> __pospos = + __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); + + std::iter_swap(__i++, __first + __pospos.first); + std::iter_swap(__i++, __first + __pospos.second); + } + + return; + } + + __distr_type __d; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); + } +#endif // C++11 + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __f A unary function object. + * @return @p __f + * + * Applies the function object @p __f to each element in the range + * @p [first,last). @p __f must not modify the order of the sequence. + * If @p __f has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _Function + for_each(_InputIterator __first, _InputIterator __last, _Function __f) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + for (; __first != __last; ++__first) + __f(*__first); + return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant. + } + +#if __cplusplus >= 201703L + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __n A value convertible to an integer. + * @param __f A unary function object. + * @return `__first+__n` + * + * Applies the function object `__f` to each element in the range + * `[first, first+n)`. `__f` must not modify the order of the sequence. + * If `__f` has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + for_each_n(_InputIterator __first, _Size __n, _Function __f) + { + auto __n2 = std::__size_to_integer(__n); + using _Cat = typename iterator_traits<_InputIterator>::iterator_category; + if constexpr (is_base_of_v) + { + if (__n2 <= 0) + return __first; + auto __last = __first + __n2; + std::for_each(__first, __last, std::move(__f)); + return __last; + } + else + { + while (__n2-->0) + { + __f(*__first); + ++__first; + } + return __first; + } + } +#endif // C++17 + + /** + * @brief Find the first occurrence of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __val The value to find. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @c *i == @p __val, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find(_InputIterator __first, _InputIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + /** + * @brief Find the first element in a sequence for which a + * predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is true, or @p __last if no such iterator exists. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Find element from a set in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an + * iterator in [__first2,__last2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (*__first1 == *__iter) + return __first1; + return __last1; + } + + /** + * @brief Find element from a set in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @param __comp Predicate to use. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true + * and i2 is an iterator in [__first2,__last2), or @p __last1 if no + * such iterator exists. + * + + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (__comp(*__first1, *__iter)) + return __first1; + return __last1; + } + + /** + * @brief Find two adjacent values in a sequence that are equal. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1), + * or @p __last if no such iterator exists. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find two adjacent values in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that + * @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator + * exists. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * @brief Count the number of copies of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be counted. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @c *i == @p __value + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count(_InputIterator __first, _InputIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Count the elements of a sequence for which a predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @p __pred(*i) is true. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Search a sequence for a matching sub-sequence. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @return The first iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p + * *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the first element + * of the sub-sequence, or @p __last1 if the sub-sequence is not + * found. + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. + * + * This means that the returned iterator @c i will be in the range + * @p [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Search a sequence for a number of consecutive values. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @c *(i+N) == @p __val for + * each @c N in the range @p [0,__count), or @p __last if no such + * iterator exists. + * + * Searches the range @p [__first,__last) for @p count consecutive elements + * equal to @p __val. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + + /** + * @brief Search a sequence for a number of consecutive values using a + * predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @p + * __binary_pred(*(i+N),__val) is true for each @c N in the range + * @p [0,__count), or @p __last if no such iterator exists. + * + * Searches the range @p [__first,__last) for @p __count + * consecutive elements for which the predicate returns true. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); + } + +#if __cplusplus >= 201703L + /** @brief Search a sequence using a Searcher object. + * + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __searcher A callable object. + * @return @p __searcher(__first,__last).first + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search(_ForwardIterator __first, _ForwardIterator __last, + const _Searcher& __searcher) + { return __searcher(__first, __last).first; } +#endif + + /** + * @brief Perform an operation on a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __unary_op A unary operator. + * @return An output iterator equal to @p __result+(__last-__first). + * + * Applies the operator to each element in the input range and assigns + * the results to successive elements of the output sequence. + * Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the + * range @p [0,__last-__first). + * + * @p unary_op must not alter its argument. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _UnaryOperation __unary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _UnaryOperation" + __typeof__(__unary_op(*__first))>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first, (void)++__result) + *__result = __unary_op(*__first); + return __result; + } + + /** + * @brief Perform an operation on corresponding elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __result An output iterator. + * @param __binary_op A binary operator. + * @return An output iterator equal to @p result+(last-first). + * + * Applies the operator to the corresponding elements in the two + * input ranges and assigns the results to successive elements of the + * output sequence. + * Evaluates @p + * *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each + * @c N in the range @p [0,__last1-__first1). + * + * @p binary_op must not alter either of its arguments. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _OutputIterator __result, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _BinaryOperation" + __typeof__(__binary_op(*__first1,*__first2))>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result) + *__result = __binary_op(*__first1, *__first2); + return __result; + } + + /** + * @brief Replace each occurrence of one value in a sequence with another + * value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return replace() returns no value. + * + * For each iterator `i` in the range `[__first,__last)` if + * `*i == __old_value` then the assignment `*i = __new_value` is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (*__first == __old_value) + *__first = __new_value; + } + + /** + * @brief Replace each value in a sequence for which a predicate returns + * true with another value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return replace_if() returns no value. + * + * For each iterator `i` in the range `[__first,__last)` if `__pred(*i)` + * is true then the assignment `*i = __new_value` is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + *__first = __new_value; + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __gen A function object callable with no arguments. + * @return generate() returns no value. + * + * Performs the assignment `*i = __gen()` for each `i` in the range + * `[__first, __last)`. + */ + template + _GLIBCXX20_CONSTEXPR + void + generate(_ForwardIterator __first, _ForwardIterator __last, + _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_GeneratorConcept<_Generator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + *__first = __gen(); + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __n The length of the sequence. + * @param __gen A function object callable with no arguments. + * @return The end of the sequence, i.e., `__first + __n` + * + * Performs the assignment `*i = __gen()` for each `i` in the range + * `[__first, __first + __n)`. + * + * If `__n` is negative, the function does nothing and returns `__first`. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + generate_n(_OutputIterator __first, _Size __n, _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _Generator" + __typeof__(__gen())>) + + typedef __decltype(std::__size_to_integer(__n)) _IntSize; + for (_IntSize __niter = std::__size_to_integer(__n); + __niter > 0; --__niter, (void) ++__first) + *__first = __gen(); + return __first; + } + + /** + * @brief Copy a sequence, removing consecutive duplicate values. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range `[__first, __last)` to the range + * beginning at `__result`, except that only the first element is copied + * from groups of consecutive elements that compare equal. + * `unique_copy()` is stable, so the relative order of elements that are + * copied is unchanged. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 241. Does unique_copy() require CopyConstructible and Assignable? + // DR 538. 241 again: Does unique_copy() require CopyConstructible and + // Assignable? + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_equal_to_iter(), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + + /** + * @brief Copy a sequence, removing consecutive values using a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range `[__first, __last)` to the range + * beginning at `__result`, except that only the first element is copied + * from groups of consecutive elements for which `__binary_pred` returns + * true. + * `unique_copy()` is stable, so the relative order of elements that are + * copied is unchanged. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 241. Does unique_copy() require CopyConstructible and Assignable? + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryPredicate __binary_pred) + { + // concept requirements -- predicates checked later + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + +#if __cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED +#if _GLIBCXX_HOSTED + /** + * @brief Randomly shuffle the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return Nothing. + * + * Reorder the elements in the range `[__first, __last)` using a random + * distribution, so that every possible ordering of the sequence is + * equally likely. + * + * @deprecated + * Since C++17, `std::random_shuffle` is not part of the C++ standard. + * Use `std::shuffle` instead, which was introduced in C++11. + */ + template + _GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle") + inline void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first != __last) + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + // XXX rand() % N is not uniformly distributed + _RandomAccessIterator __j = __first + + std::rand() % ((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } + + /** + * @brief Shuffle the elements of a sequence using a random number + * generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __rand The RNG functor or function. + * @return Nothing. + * + * Reorders the elements in the range `[__first, __last)` using `__rand` + * to provide a random distribution. Calling `__rand(N)` for a positive + * integer `N` should return a randomly chosen integer from the + * range `[0, N)`. + * + * @deprecated + * Since C++17, `std::random_shuffle` is not part of the C++ standard. + * Use `std::shuffle` instead, which was introduced in C++11. + */ + template + _GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle") + void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, +#if __cplusplus >= 201103L + _RandomNumberGenerator&& __rand) +#else + _RandomNumberGenerator& __rand) +#endif + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } +#endif // HOSTED +#endif // <= C++11 || USE_DEPRECATED + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator `middle` such that `__pred(i)` is true for each + * iterator `i` in the range `[__first, middle)` and false for each `i` + * in the range `[middle, __last)`. + * + * `__pred` must not modify its operand. `partition()` does not preserve + * the relative ordering of elements in each group, use + * `stable_partition()` if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__partition(__first, __last, __pred, + std::__iterator_category(__first)); + } + + + /** + * @brief Sort the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the smallest `(__middle - __first)` elements in the range + * `[first, last)` and moves them to the range `[__first, __middle)`. The + * order of the remaining elements in the range `[__middle, __last)` is + * unspecified. + * After the sort if `i` and `j` are iterators in the range + * `[__first, __middle)` such that `i` precedes `j` and `k` is an iterator + * in the range `[__middle, __last)` then `*j < *i` and `*k < *i` are + * both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the smallest elements of a sequence using a predicate + * for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the smallest `(__middle - __first)` elements in the range + * `[__first, __last)` and moves them to the range `[__first, __middle)`. + * The order of the remaining elements in the range `[__middle, __last)` is + * unspecified. + * After the sort if `i` and `j` are iterators in the range + * `[__first, __middle)` such that `i` precedes `j` and `k` is an iterator + * in the range `[__middle, __last)` then `*__comp(j, *i)` and + * `__comp(*k, *i)` are both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort a sequence just enough to find a particular position. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Rearranges the elements in the range `[__first, __last)` so that `*__nth` + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of `*__nth` are + * not completely sorted, but for any iterator `i` in the range + * `[__first, __nth)` and any iterator `j` in the range `[__nth, __last)` it + * holds that `*j < *i` is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive(__first, __last); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort a sequence just enough to find a particular position + * using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Rearranges the elements in the range `[__first, __last)` so that `*__nth` + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of `*__nth` are + * not completely sorted, but for any iterator `i` in the range + * `[__first, __nth)` and any iterator `j` in the range `[__nth, __last)` + * it holds that `__comp(*j, *i)` is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort the elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range `[__first, __last)` in ascending order, + * such that for each iterator `i` in the range `[__first, __last - 1)`, + * `*(i+1) < *i` is false. + * + * The relative ordering of equivalent elements is not preserved, use + * `stable_sort()` if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range `[__first, __last)` in ascending order, + * such that `__comp(*(i+1), *i)` is false for every iterator `i` in the + * range `[__first, __last - 1)`. + * + * The relative ordering of equivalent elements is not preserved, use + * `stable_sort()` if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @param __comp A functor to use for comparisons. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + inline void + __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + if (__first == __last) + return; + +#if _GLIBCXX_HOSTED + typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf; + // __stable_sort_adaptive sorts the range in two halves, + // so the buffer only needs to fit half the range at once. + _TmpBuf __buf(__first, (__last - __first + 1) / 2); + + if (__builtin_expect(__buf.requested_size() == __buf.size(), true)) + std::__stable_sort_adaptive(__first, + __first + _DistanceType(__buf.size()), + __last, __buf.begin(), __comp); + else if (__builtin_expect(__buf.begin() == 0, false)) + std::__inplace_stable_sort(__first, __last, __comp); + else + std::__stable_sort_adaptive_resize(__first, __last, __buf.begin(), + _DistanceType(__buf.size()), __comp); +#else + std::__inplace_stable_sort(__first, __last, __comp); +#endif + } + + /** + * @brief Sort the elements of a sequence, preserving the relative order + * of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p *(i+1)<*i is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p x + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison, + * preserving the relative order of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p __comp(*(i+1),*i) is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p __comp(x,y) is false and @p __comp(y,x) is false will have the same + * relative ordering after calling @p stable_sort(). + */ + template + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the union of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that element is copied and the iterator advanced. If an element is + * contained in both ranges, the element from the first range is copied and + * both ranges advance. The output range may not overlap either input + * range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the union of two sorted ranges using a comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that element is copied and the iterator advanced. + * If an equivalent element according to @p __comp is contained in both + * ranges, the element from the first range is copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + ++__first1; + else if (__comp(__first2, __first1)) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + return __result; + } + + /** + * @brief Return the intersection of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that iterator advances. If an element is contained in both ranges, the + * element from the first range is copied and both ranges advance. The + * output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the intersection of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that iterator advances. If an element is + * contained in both ranges according to @p __comp, the element from the + * first range is copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return std::copy(__first1, __last1, __result); + } + + /** + * @brief Return the difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second, that element is copied and the + * iterator advances. If the current element of the second range is less, + * the iterator advances, but no element is copied. If an element is + * contained in both ranges, no elements are copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the difference of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second according to @p __comp, that element + * is copied and the iterator advances. If the current element of the + * second range is less, no element is copied and the iterator advances. + * If an element is contained in both ranges according to @p __comp, no + * elements are copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_symmetric_difference(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the symmetric difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other, that element is copied and the iterator advances. If an + * element is contained in both ranges, no elements are copied and both + * ranges advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the symmetric difference of two sorted ranges using + * comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other according to @p comp, that element is copied and the + * iterator advances. If an element is contained in both ranges according + * to @p __comp, no elements are copied and both ranges advance. The output + * range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__first, __result)) + __result = __first; + return __result; + } + + /** + * @brief Return the minimum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the smallest value. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + _ForwardIterator + inline min_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the minimum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the smallest value + * according to __comp. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__result, __first)) + __result = __first; + return __result; + } + + /** + * @brief Return the maximum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the largest value. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the maximum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the largest value + * according to __comp. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201103L + // N2722 + DR 915. + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l) + { + __glibcxx_requires_irreflexive(__l.begin(), __l.end()); + return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_less_iter()); + } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l, _Compare __comp) + { + __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); + return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l) + { + __glibcxx_requires_irreflexive(__l.begin(), __l.end()); + return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_less_iter()); + } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l, _Compare __comp) + { + __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); + return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } +#endif // C++11 + +#if __cplusplus >= 201402L + /// Reservoir sampling algorithm. + template + _RandomAccessIterator + __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, + _RandomAccessIterator __out, random_access_iterator_tag, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + _Size __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + + /// Selection sampling algorithm. + template + _OutputIterator + __sample(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag, + _OutputIterator __out, _Cat, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + using _USize = make_unsigned_t<_Size>; + using _Gen = remove_reference_t<_UniformRandomBitGenerator>; + using __uc_type = common_type_t; + + if (__first == __last) + return __out; + + __distrib_type __d{}; + _Size __unsampled_sz = std::distance(__first, __last); + __n = std::min(__n, __unsampled_sz); + + // If possible, we use __gen_two_uniform_ints to efficiently produce + // two random numbers using a single distribution invocation: + + const __uc_type __urngrange = __g.max() - __g.min(); + if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) + // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without + // wrapping issues. + { + while (__n != 0 && __unsampled_sz >= 2) + { + const pair<_Size, _Size> __p = + __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); + + --__unsampled_sz; + if (__p.first < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + + if (__n == 0) break; + + --__unsampled_sz; + if (__p.second < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + } + } + + // The loop above is otherwise equivalent to this one-at-a-time version: + + for (; __n != 0; ++__first) + if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) + { + *__out++ = *__first; + --__n; + } + return __out; + } +#endif // C++14 + +#ifdef __glibcxx_sample // C++ >= 17 + /// Take a random sample from a population. + template + _SampleIterator + sample(_PopulationIterator __first, _PopulationIterator __last, + _SampleIterator __out, _Distance __n, + _UniformRandomBitGenerator&& __g) + { + using __pop_cat = typename + std::iterator_traits<_PopulationIterator>::iterator_category; + using __samp_cat = typename + std::iterator_traits<_SampleIterator>::iterator_category; + + static_assert( + __or_, + is_convertible<__samp_cat, random_access_iterator_tag>>::value, + "output range must use a RandomAccessIterator when input range" + " does not meet the ForwardIterator requirements"); + + static_assert(is_integral<_Distance>::value, + "sample size must be an integer type"); + + typename iterator_traits<_PopulationIterator>::difference_type __d = __n; + return _GLIBCXX_STD_A:: + __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d, + std::forward<_UniformRandomBitGenerator>(__g)); + } +#endif // __glibcxx_sample + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_ALGO_H */ diff --git a/template/sysroot/include/bits/stl_algobase.h b/template/sysroot/include/bits/stl_algobase.h new file mode 100644 index 0000000..f0fbf22 --- /dev/null +++ b/template/sysroot/include/bits/stl_algobase.h @@ -0,0 +1,2352 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGOBASE_H +#define _STL_ALGOBASE_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // For std::swap +#include +#if __cplusplus >= 201103L +# include +#endif +#if __cplusplus >= 201402L +# include // std::__bit_width +#endif +#if __cplusplus >= 202002L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + * A constexpr wrapper for __builtin_memcmp. + * @param __num The number of elements of type _Tp (not bytes). + */ + template + _GLIBCXX14_CONSTEXPR + inline int + __memcmp(const _Tp* __first1, const _Up* __first2, size_t __num) + { +#if __cplusplus >= 201103L + static_assert(sizeof(_Tp) == sizeof(_Up), "can be compared with memcmp"); +#endif +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for(; __num > 0; ++__first1, ++__first2, --__num) + if (*__first1 != *__first2) + return *__first1 < *__first2 ? -1 : 1; + return 0; + } + else +#endif + return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num); + } + +#if __cplusplus < 201103L + // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a + // nutshell, we are partially implementing the resolution of DR 187, + // when it's safe, i.e., the value_types are equal. + template + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + _ValueType1 __tmp = *__a; + *__a = *__b; + *__b = __tmp; + } + }; + + template<> + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + swap(*__a, *__b); + } + }; +#endif // C++03 + + /** + * @brief Swaps the contents of two iterators. + * @ingroup mutating_algorithms + * @param __a An iterator. + * @param __b Another iterator. + * @return Nothing. + * + * This function swaps the values pointed to by two iterators, not the + * iterators themselves. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + +#if __cplusplus < 201103L + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator2>::value_type + _ValueType2; + + __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, + _ValueType2>) + __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, + _ValueType1>) + + typedef typename iterator_traits<_ForwardIterator1>::reference + _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference + _ReferenceType2; + std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value + && __are_same<_ValueType1&, _ReferenceType1>::__value + && __are_same<_ValueType2&, _ReferenceType2>::__value>:: + iter_swap(__a, __b); +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 187. iter_swap underspecified + swap(*__a, *__b); +#endif + } + + /** + * @brief Swap the elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @return An iterator equal to @p first2+(last1-first1). + * + * Swaps each element in the range @p [first1,last1) with the + * corresponding element in the range @p [first2,(last1-first1)). + * The ranges must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator2 + swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + std::iter_swap(__first1, __first2); + return __first2; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The lesser of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __b < __a ? __b : __a; + if (__b < __a) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The greater of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __a < __b ? __b : __a; + if (__a < __b) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The lesser of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__b, __a) ? __b : __a; + if (__comp(__b, __a)) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The greater of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__a, __b) ? __b : __a; + if (__comp(__a, __b)) + return __b; + return __a; + } + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the __normal_iterator wrapper. See copy, fill, ... + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_base(_Iterator __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it; } + +#if __cplusplus < 201103L + template + _Ite + __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, + std::random_access_iterator_tag>&); + + template + _Ite + __niter_base(const ::__gnu_debug::_Safe_iterator< + ::__gnu_cxx::__normal_iterator<_Ite, _Cont>, _Seq, + std::random_access_iterator_tag>&); +#else + template + _GLIBCXX20_CONSTEXPR + decltype(std::__niter_base(std::declval<_Ite>())) + __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, + std::random_access_iterator_tag>&) + noexcept(std::is_nothrow_copy_constructible<_Ite>::value); +#endif + + // Reverse the __niter_base transformation to get a + // __normal_iterator back again (this assumes that __normal_iterator + // is only used to wrap random access iterators, like pointers). + template + _GLIBCXX20_CONSTEXPR + inline _From + __niter_wrap(_From __from, _To __res) + { return __from + (std::__niter_base(__res) - std::__niter_base(__from)); } + + // No need to wrap, iterator already has the right type. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_wrap(const _Iterator&, _Iterator __res) + { return __res; } + + // All of these auxiliary structs serve two purposes. (1) Replace + // calls to copy with memmove whenever possible. (Memmove, not memcpy, + // because the input and output ranges are permitted to overlap.) + // (2) If we're using random access iterators, then write the loop as + // a for loop with an explicit count. + + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = *__first; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = std::move(*__first); + return __result; + } + }; +#endif + + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = *__first; + ++__first; + ++__result; + } + return __result; + } + + template + static void + __assign_one(_Tp* __to, _Up* __from) + { *__to = *__from; } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = std::move(*__first); + ++__first; + ++__result; + } + return __result; + } + + template + static void + __assign_one(_Tp* __to, _Up* __from) + { *__to = std::move(*__from); } + }; +#endif + + template + struct __copy_move<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Up* + __copy_m(_Tp* __first, _Tp* __last, _Up* __result) + { + const ptrdiff_t _Num = __last - __first; + if (__builtin_expect(_Num > 1, true)) + __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); + else if (_Num == 1) + std::__copy_move<_IsMove, false, random_access_iterator_tag>:: + __assign_one(__result, __first); + return __result + _Num; + } + }; + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + struct _Deque_iterator; + + struct _Bit_iterator; + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if _GLIBCXX_HOSTED + // Helpers for streambuf iterators (either istream or ostream). + // NB: avoid including , relatively large. + template + struct char_traits; + + template + class istreambuf_iterator; + + template + class ostreambuf_iterator; + + template + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type + __copy_move_a2(_CharT*, _CharT*, + ostreambuf_iterator<_CharT, char_traits<_CharT> >); + + template + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type + __copy_move_a2(const _CharT*, const _CharT*, + ostreambuf_iterator<_CharT, char_traits<_CharT> >); + + template + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + _CharT*>::__type + __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >, + istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*); + + template + typename __gnu_cxx::__enable_if< + __is_char<_CharT>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type + __copy_move_a2( + istreambuf_iterator<_CharT, char_traits<_CharT> >, + istreambuf_iterator<_CharT, char_traits<_CharT> >, + _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>); +#endif // HOSTED + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a2(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move<_IsMove, false, _Category>:: + __copy_m(__first, __last, __result); +#endif + return std::__copy_move<_IsMove, __memcpyable<_OI, _II>::__value, + _Category>::__copy_m(__first, __last, __result); + } + + template + _OI + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a1(_II __first, _II __last, _OI __result) + { return std::__copy_move_a2<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_a1<_IsMove>(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result))); + } + + template + _GLIBCXX20_CONSTEXPR + _OI + __copy_move_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + _OI); + + template + _GLIBCXX20_CONSTEXPR + __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> + __copy_move_a(_II, _II, + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); + + template + _GLIBCXX20_CONSTEXPR + ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> + __copy_move_a(const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, + const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, + const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&); + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result, + bool) + { + if (__n > 0) + { + while (true) + { + *__result = *__first; + ++__result; + if (--__n > 0) + ++__first; + else + break; + } + } + return __result; + } + +#if _GLIBCXX_HOSTED + template + typename __gnu_cxx::__enable_if< + __is_char<_CharT>::__value, _CharT*>::__type + __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >, + _Size, _CharT*, bool); + + template + typename __gnu_cxx::__enable_if< + __is_char<_CharT>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type + __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >, _Size, + _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>, + bool); +#endif + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the copy_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + copy(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::reference>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a<__is_move_iterator<_II>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the move_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + move(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::value_type&&>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a(std::__miter_base(__first), + std::__miter_base(__last), __result); + } + +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) +#endif + + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template + struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Up* + __copy_move_b(_Tp* __first, _Tp* __last, _Up* __result) + { + const ptrdiff_t _Num = __last - __first; + if (__builtin_expect(_Num > 1, true)) + __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); + else if (_Num == 1) + std::__copy_move<_IsMove, false, random_access_iterator_tag>:: + __assign_one(__result - 1, __first); + return __result - _Num; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) + { + typedef typename iterator_traits<_BI1>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move_backward<_IsMove, false, _Category>:: + __copy_move_b(__first, __last, __result); +#endif + return std::__copy_move_backward<_IsMove, + __memcpyable<_BI2, _BI1>::__value, + _Category>::__copy_move_b(__first, + __last, + __result); + } + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) + { return std::__copy_move_backward_a2<_IsMove>(__first, __last, __result); } + + template + _OI + __copy_move_backward_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_backward_a1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_backward_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_backward_a1<_IsMove> + (std::__niter_base(__first), std::__niter_base(__last), + std::__niter_base(__result))); + } + + template + _GLIBCXX20_CONSTEXPR + _OI + __copy_move_backward_a( + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + _OI); + + template + _GLIBCXX20_CONSTEXPR + __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> + __copy_move_backward_a(_II, _II, + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); + + template + _GLIBCXX20_CONSTEXPR + ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> + __copy_move_backward_a( + const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, + const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, + const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&); + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as copy, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use copy instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_OutputIteratorConcept<_BI2, + typename iterator_traits<_BI1>::reference>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a<__is_move_iterator<_BI1>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as move, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use move instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + move_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_OutputIteratorConcept<_BI2, + typename iterator_traits<_BI1>::value_type&&>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a(std::__miter_base(__first), + std::__miter_base(__last), + __result); + } + +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp) +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + for (; __first != __last; ++__first) + *__first = __value; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + } + + // Specialization: for char types we can use memset. + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type + __fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c) + { + const _Tp __tmp = __c; +#if __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for (; __first != __last; ++__first) + *__first = __tmp; + return; + } +#endif + if (const size_t __len = __last - __first) + __builtin_memset(__first, static_cast(__tmp), __len); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first, + ::__gnu_cxx::__normal_iterator<_Ite, _Cont> __last, + const _Tp& __value) + { std::__fill_a1(__first.base(), __last.base(), __value); } + + template + void + __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _VTp&); + + _GLIBCXX20_CONSTEXPR + void + __fill_a1(_GLIBCXX_STD_C::_Bit_iterator, _GLIBCXX_STD_C::_Bit_iterator, + const bool&); + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a(_FIte __first, _FIte __last, const _Tp& __value) + { std::__fill_a1(__first, __last, __value); } + + template + _GLIBCXX20_CONSTEXPR + void + __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, + const _Tp&); + + /** + * @brief Fills the range [first,last) with copies of value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __value A reference-to-const of arbitrary type. + * @return Nothing. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __last); + + std::__fill_a(__first, __last, __value); + } + + // Used by fill_n, generate_n, etc. to convert _Size to an integral type: + inline _GLIBCXX_CONSTEXPR int + __size_to_integer(int __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned + __size_to_integer(unsigned __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long + __size_to_integer(long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long + __size_to_integer(unsigned long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long long + __size_to_integer(unsigned long long __n) { return __n; } + +#if defined(__GLIBCXX_TYPE_INT_N_0) + __extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(__GLIBCXX_TYPE_INT_N_0 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_0 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + __extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(__GLIBCXX_TYPE_INT_N_1 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_1 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + __extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(__GLIBCXX_TYPE_INT_N_2 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; } +#endif + + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(float __n) { return (long long)__n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(double __n) { return (long long)__n; } +#if !(defined(__clang__) && !__STDC_HOSTED__) // clang in kernel context + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long double __n) { return (long long)__n; } +#endif +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + __extension__ inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(__float128 __n) { return (long long)__n; } +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + for (; __n > 0; --__n, (void) ++__first) + *__first = __value; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __n > 0; --__n, (void) ++__first) + *__first = __tmp; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> + __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, + _Size __n, const _Tp& __value, + std::input_iterator_tag); + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::output_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::input_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::random_access_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + if (__n <= 0) + return __first; + + __glibcxx_requires_can_increment(__first, __n); + + std::__fill_a(__first, __first + __n, __value); + return __first + __n; + } + + /** + * @brief Fills the range [first,first+n) with copies of value. + * @ingroup mutating_algorithms + * @param __first An output iterator. + * @param __n The count of copies to perform. + * @param __value A reference-to-const of arbitrary type. + * @return The iterator at first+n. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + * + * If @p __n is negative, the function does nothing. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + inline _OI + fill_n(_OI __first, _Size __n, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OI, const _Tp&>) + + return std::__fill_n_a(__first, std::__size_to_integer(__n), __value, + std::__iterator_category(__first)); + } + + template + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + for (; __first1 != __last1; ++__first1, (void) ++__first2) + if (!(*__first1 == *__first2)) + return false; + return true; + } + }; + + template<> + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + }; + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _II); + + template + bool + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>); + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux1(_II1 __first1, _II1 __last1, _II2 __first2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + const bool __simple = ((__is_integer<_ValueType1>::__value + || __is_pointer<_ValueType1>::__value) + && __memcmpable<_II1, _II2>::__value); + return std::__equal<__simple>::equal(__first1, __last1, __first2); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) + { + return std::__equal_aux1(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2)); + } + + template + _GLIBCXX20_CONSTEXPR + bool + __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, + _II2); + + template + _GLIBCXX20_CONSTEXPR + bool + __equal_aux(_II1, _II1, + const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); + + template + _GLIBCXX20_CONSTEXPR + bool + __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); + + template + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _II1 + __newlast1(_II1, _II1 __last1, _II2, _II2) + { return __last1; } + + template + _GLIBCXX20_CONSTEXPR + static bool + __cnd2(_II __first, _II __last) + { return __first != __last; } + }; + + template<> + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _RAI1 + __newlast1(_RAI1 __first1, _RAI1 __last1, + _RAI2 __first2, _RAI2 __last2) + { + const typename iterator_traits<_RAI1>::difference_type + __diff1 = __last1 - __first1; + const typename iterator_traits<_RAI2>::difference_type + __diff2 = __last2 - __first2; + return __diff2 < __diff1 ? __first1 + __diff2 : __last1; + } + + template + static _GLIBCXX20_CONSTEXPR bool + __cnd2(_RAI, _RAI) + { return true; } + }; + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_impl(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, + _Compare __comp) + { + typedef typename iterator_traits<_II1>::iterator_category _Category1; + typedef typename iterator_traits<_II2>::iterator_category _Category2; + typedef std::__lc_rai<_Category1, _Category2> __rai_type; + + __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); + for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); + ++__first1, (void)++__first2) + { + if (__comp(__first1, __first2)) + return true; + if (__comp(__first2, __first1)) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + template + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using __gnu_cxx::__ops::__iter_less_iter; + return std::__lexicographical_compare_impl(__first1, __last1, + __first2, __last2, + __iter_less_iter()); + } + + template + _GLIBCXX20_CONSTEXPR + static int + __3way(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + while (__first1 != __last1) + { + if (__first2 == __last2) + return +1; + if (*__first1 < *__first2) + return -1; + if (*__first2 < *__first1) + return +1; + ++__first1; + ++__first2; + } + return int(__first2 == __last2) - 1; + } + }; + + template<> + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(const _Tp* __first1, const _Tp* __last1, + const _Up* __first2, const _Up* __last2) + { return __3way(__first1, __last1, __first2, __last2) < 0; } + + template + _GLIBCXX20_CONSTEXPR + static ptrdiff_t + __3way(const _Tp* __first1, const _Tp* __last1, + const _Up* __first2, const _Up* __last2) + { + const size_t __len1 = __last1 - __first1; + const size_t __len2 = __last2 - __first2; + if (const size_t __len = std::min(__len1, __len2)) + if (int __result = std::__memcmp(__first1, __first2, __len)) + return __result; + return ptrdiff_t(__len1 - __len2); + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline bool + __lexicographical_compare_aux1(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + const bool __simple = + (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __is_pointer<_II1>::__value + && __is_pointer<_II2>::__value +#if __cplusplus > 201703L && __glibcxx_concepts + // For C++20 iterator_traits::value_type is non-volatile + // so __is_byte could be true, but we can't use memcmp with + // volatile data. + && !is_volatile_v>> + && !is_volatile_v>> +#endif + ); + + return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, + __first2, __last2); + } + + template + bool + __lexicographical_compare_aux1( + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _Tp2*, _Tp2*); + + template + bool + __lexicographical_compare_aux1(_Tp1*, _Tp1*, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); + + template + bool + __lexicographical_compare_aux1( + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); + + template + _GLIBCXX20_CONSTEXPR + inline bool + __lexicographical_compare_aux(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + return std::__lexicographical_compare_aux1(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2), + std::__niter_base(__last2)); + } + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_aux( + const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, + _II2, _II2); + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_aux( + _II1, _II1, + const ::__gnu_debug::_Safe_iterator<_Iter2, _Seq2, _Cat2>&, + const ::__gnu_debug::_Safe_iterator<_Iter2, _Seq2, _Cat2>&); + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_aux( + const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, + const ::__gnu_debug::_Safe_iterator<_Iter2, _Seq2, _Cat2>&, + const ::__gnu_debug::_Safe_iterator<_Iter2, _Seq2, _Cat2>&); + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + /** + * @brief Finds the first position in which @a val could be inserted + * without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element not less + * than @a val, or end() if every element is less than + * @a val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + } + + /// This is a helper function for the sort routines and for random.tcc. + // Precondition: __n > 0. + template + inline _GLIBCXX_CONSTEXPR _Tp + __lg(_Tp __n) + { +#if __cplusplus >= 201402L + return std::__bit_width(make_unsigned_t<_Tp>(__n)) - 1; +#else + // Use +__n so it promotes to at least int. + return (sizeof(+__n) * __CHAR_BIT__ - 1) + - (sizeof(+__n) == sizeof(long long) + ? __builtin_clzll(+__n) + : (sizeof(+__n) == sizeof(long) + ? __builtin_clzl(+__n) + : __builtin_clz(+__n))); +#endif + } + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_can_increment_range(__first1, __last1, __first2); + + return std::__equal_aux(__first1, __last1, __first2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return true; + } + +#if __cplusplus >= 201103L + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(*__first1 == *__first2)) + return false; + return __first1 == __last1 && __first2 == __last2; + } + + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, + _BinaryPredicate __binary_pred) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2, + __binary_pred); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } +#endif // C++11 + +#ifdef __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14 + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2, + __binary_pred); + } +#endif // __glibcxx_robust_nonmodifying_seq_ops + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * Returns true if the sequence of elements defined by the range + * [first1,last1) is lexicographically less than the sequence of elements + * defined by the range [first2,last2). Returns false otherwise. + * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, + * then this is an inline call to @c memcmp. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; +#endif + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_aux(__first1, __last1, + __first2, __last2); + } + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return A boolean true or false. + * + * The same as the four-parameter @c lexicographical_compare, but uses the + * comp parameter instead of @c <. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_impl + (__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cpp_lib_three_way_comparison + // Both iterators refer to contiguous ranges of unsigned narrow characters, + // or std::byte, or big-endian unsigned integers, suitable for comparison + // using memcmp. + template + concept __memcmp_ordered_with + = (__is_memcmp_ordered_with, + iter_value_t<_Iter2>>::__value) + && contiguous_iterator<_Iter1> && contiguous_iterator<_Iter2>; + + // Return a struct with two members, initialized to the smaller of x and y + // (or x if they compare equal) and the result of the comparison x <=> y. + template + constexpr auto + __min_cmp(_Tp __x, _Tp __y) + { + struct _Res { + _Tp _M_min; + decltype(__x <=> __y) _M_cmp; + }; + auto __c = __x <=> __y; + if (__c > 0) + return _Res{__y, __c}; + return _Res{__x, __c}; + } + + /** + * @brief Performs dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The comparison category that `__comp(*__first1, *__first2)` + * returns. + */ + template + [[nodiscard]] constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2, + _Comp __comp) + -> decltype(__comp(*__first1, *__first2)) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + using _Cat = decltype(__comp(*__first1, *__first2)); + static_assert(same_as, _Cat>); + + if (!std::__is_constant_evaluated()) + if constexpr (same_as<_Comp, __detail::_Synth3way> + || same_as<_Comp, compare_three_way>) + if constexpr (__memcmp_ordered_with<_InputIter1, _InputIter2>) + { + const auto [__len, __lencmp] = _GLIBCXX_STD_A:: + __min_cmp(__last1 - __first1, __last2 - __first2); + if (__len) + { + const auto __blen = __len * sizeof(*__first1); + const auto __c + = __builtin_memcmp(&*__first1, &*__first2, __blen) <=> 0; + if (__c != 0) + return __c; + } + return __lencmp; + } + + while (__first1 != __last1) + { + if (__first2 == __last2) + return strong_ordering::greater; + if (auto __cmp = __comp(*__first1, *__first2); __cmp != 0) + return __cmp; + ++__first1; + ++__first2; + } + return (__first2 == __last2) <=> true; // See PR 94006 + } + + template + constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2) + { + return _GLIBCXX_STD_A:: + lexicographical_compare_three_way(__first1, __last1, __first2, __last2, + compare_three_way{}); + } +#endif // three_way_comparison + + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + +#if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14 + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __first2 != __last2 + && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } +#endif + +_GLIBCXX_END_NAMESPACE_ALGO + + /// This is an overload used by find algos for the Input Iterator case. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred, input_iterator_tag) + { + while (__first != __last && !__pred(__first)) + ++__first; + return __first; + } + + /// This is an overload used by find algos for the RAI case. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Predicate __pred, random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIterator>::difference_type + __trip_count = (__last - __first) >> 2; + + for (; __trip_count > 0; --__trip_count) + { + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + } + + switch (__last - __first) + { + case 3: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 2: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 1: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 0: + default: + return __last; + } + } + + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __find_if(_Iterator __first, _Iterator __last, _Predicate __pred) + { + return __find_if(__first, __last, __pred, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + typename iterator_traits<_InputIterator>::difference_type __n = 0; + for (; __first != __last; ++__first) + if (__pred(__first)) + ++__n; + return __n; + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if(__first, __last, __pred); + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = _GLIBCXX_MOVE(*__first); + ++__result; + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // Test for empty ranges + if (__first1 == __last1 || __first2 == __last2) + return __first1; + + // Test for a pattern of length 1. + _ForwardIterator2 __p1(__first2); + if (++__p1 == __last2) + return std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + // General case. + _ForwardIterator1 __current = __first1; + + for (;;) + { + __first1 = + std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + if (__first1 == __last1) + return __last1; + + _ForwardIterator2 __p = __p1; + __current = __first1; + if (++__current == __last1) + return __last1; + + while (__predicate(__current, __p)) + { + if (++__p == __last2) + return __first1; + if (++__current == __last1) + return __last1; + } + ++__first1; + } + return __first1; + } + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__first1 == __last1) + return true; + + // Establish __last2 assuming equal ranges by iterating over the + // rest of the list. + _ForwardIterator2 __last2 = __first2; + std::advance(__last2, std::distance(__first1, __last1)); + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches + = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches || + std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __first2 + (__last1 - __first1)), beginning with + * ForwardIterator2 begin, such that equal(__first1, __last1, begin) + * returns true; otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } +#endif // C++11 + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Search a sequence for a matching sub-sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @param __predicate A binary predicate. + * @return The first iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that + * @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range + * @p [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2), using @p __predicate to determine equality, + * and returns an iterator to the first element of the + * sub-sequence, or @p __last1 if no such iterator exists. + * + * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__predicate)); + } + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +// NB: This file is included within many other C++ includes, as a way +// of getting the base algorithms. So, make sure that parallel bits +// come in too if requested. +#ifdef _GLIBCXX_PARALLEL +# include +#endif + +#endif diff --git a/template/sysroot/include/bits/stl_construct.h b/template/sysroot/include/bits/stl_construct.h new file mode 100644 index 0000000..dc08fb7 --- /dev/null +++ b/template/sysroot/include/bits/stl_construct.h @@ -0,0 +1,267 @@ +// nonstandard construct and destroy functions -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_construct.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_CONSTRUCT_H +#define _STL_CONSTRUCT_H 1 + +#include +#include +#include // for iterator_traits +#include // for advance + +/* This file provides the C++17 functions std::destroy_at, std::destroy, and + * std::destroy_n, and the C++20 function std::construct_at. + * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions + * which are defined in all standard modes and so can be used in C++98-14 code. + * The _Destroy functions will dispatch to destroy_at during constant + * evaluation, because calls to that function are intercepted by the compiler + * to allow use in constant expressions. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __glibcxx_raw_memory_algorithms // >= C++17 + template + _GLIBCXX20_CONSTEXPR inline void + destroy_at(_Tp* __location) + { + if constexpr (__cplusplus > 201703L && is_array_v<_Tp>) + { + for (auto& __x : *__location) + std::destroy_at(std::__addressof(__x)); + } + else + __location->~_Tp(); + } + +#if __cpp_constexpr_dynamic_alloc // >= C++20 + template + constexpr auto + construct_at(_Tp* __location, _Args&&... __args) + noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...))) + -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...)) + { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); } +#endif // C++20 +#endif// C++17 + + /** + * Constructs an object in existing memory by invoking an allocated + * object's constructor with an initializer. + */ +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + inline void + _Construct(_Tp* __p, _Args&&... __args) + { +#if __cpp_constexpr_dynamic_alloc // >= C++20 + if (std::__is_constant_evaluated()) + { + // Allow std::_Construct to be used in constant expressions. + std::construct_at(__p, std::forward<_Args>(__args)...); + return; + } +#endif + ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); + } +#else + template + inline void + _Construct(_T1* __p, const _T2& __value) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_]allocator::construct + ::new(static_cast(__p)) _T1(__value); + } +#endif + + template + inline void + _Construct_novalue(_T1* __p) + { ::new((void*)__p) _T1; } + + template + _GLIBCXX20_CONSTEXPR void + _Destroy(_ForwardIterator __first, _ForwardIterator __last); + + /** + * Destroy the object pointed to by a pointer type. + */ + template + _GLIBCXX14_CONSTEXPR inline void + _Destroy(_Tp* __pointer) + { +#if __cpp_constexpr_dynamic_alloc // >= C++20 + std::destroy_at(__pointer); +#else + __pointer->~_Tp(); +#endif + } + + template + struct _Destroy_aux + { + template + static _GLIBCXX20_CONSTEXPR void + __destroy(_ForwardIterator __first, _ForwardIterator __last) + { + for (; __first != __last; ++__first) + std::_Destroy(std::__addressof(*__first)); + } + }; + + template<> + struct _Destroy_aux + { + template + static void + __destroy(_ForwardIterator, _ForwardIterator) { } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cpp_constexpr_dynamic_alloc // >= C++20 + if (std::__is_constant_evaluated()) + return std::_Destroy_aux::__destroy(__first, __last); +#endif + std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: + __destroy(__first, __last); + } + + template + struct _Destroy_n_aux + { + template + static _GLIBCXX20_CONSTEXPR _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } + }; + + template<> + struct _Destroy_n_aux + { + template + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + std::advance(__first, __count); + return __first; + } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + _Destroy_n(_ForwardIterator __first, _Size __count) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cpp_constexpr_dynamic_alloc // >= C++20 + if (std::__is_constant_evaluated()) + return std::_Destroy_n_aux::__destroy_n(__first, __count); +#endif + return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + __destroy_n(__first, __count); + } + +#if __glibcxx_raw_memory_algorithms // >= C++17 + template + _GLIBCXX20_CONSTEXPR inline void + destroy(_ForwardIterator __first, _ForwardIterator __last) + { + std::_Destroy(__first, __last); + } + + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + destroy_n(_ForwardIterator __first, _Size __count) + { + return std::_Destroy_n(__first, __count); + } +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_CONSTRUCT_H */ diff --git a/template/sysroot/include/bits/stl_function.h b/template/sysroot/include/bits/stl_function.h new file mode 100644 index 0000000..c9123cc --- /dev/null +++ b/template/sysroot/include/bits/stl_function.h @@ -0,0 +1,1438 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _STL_FUNCTION_H +#define _STL_FUNCTION_H 1 + +#if __cplusplus > 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.1 base classes + /** @defgroup functors Function Objects + * @ingroup utilities + * + * Function objects, or _functors_, are objects with an `operator()` + * defined and accessible. They can be passed as arguments to algorithm + * templates and used in place of a function pointer. Not only is the + * resulting expressiveness of the library increased, but the generated + * code can be more efficient than what you might write by hand. When we + * refer to _functors_, then, generally we include function pointers in + * the description as well. + * + * Often, functors are only created as temporaries passed to algorithm + * calls, rather than being created as named variables. + * + * Two examples taken from the standard itself follow. To perform a + * by-element addition of two vectors `a` and `b` containing `double`, + * and put the result in `a`, use + * \code + * transform (a.begin(), a.end(), b.begin(), a.begin(), plus()); + * \endcode + * To negate every element in `a`, use + * \code + * transform(a.begin(), a.end(), a.begin(), negate()); + * \endcode + * The addition and negation functions will usually be inlined directly. + * + * An _adaptable function object_ is one which provides nested typedefs + * `result_type` and either `argument_type` (for a unary function) or + * `first_argument_type` and `second_argument_type` (for a binary function). + * Those typedefs are used by function object adaptors such as `bind2nd`. + * The standard library provides two class templates, `unary_function` and + * `binary_function`, which define those typedefs and so can be used as + * base classes of adaptable function objects. + * + * Since C++11 the use of function object adaptors has been superseded by + * more powerful tools such as lambda expressions, `function<>`, and more + * powerful type deduction (using `auto` and `decltype`). The helpers for + * defining adaptable function objects are deprecated since C++11, and no + * longer part of the standard library since C++17. However, they are still + * defined and used by libstdc++ after C++17, as a conforming extension. + * + * @{ + */ + + /** + * Helper for defining adaptable unary function objects. + * @deprecated Deprecated in C++11, no longer in the standard since C++17. + */ + template + struct unary_function + { + /// @c argument_type is the type of the argument + typedef _Arg argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + } _GLIBCXX11_DEPRECATED; + + /** + * Helper for defining adaptable binary function objects. + * @deprecated Deprecated in C++11, no longer in the standard since C++17. + */ + template + struct binary_function + { + /// @c first_argument_type is the type of the first argument + typedef _Arg1 first_argument_type; + + /// @c second_argument_type is the type of the second argument + typedef _Arg2 second_argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + } _GLIBCXX11_DEPRECATED; + /** @} */ + + // 20.3.2 arithmetic + + /** @defgroup arithmetic_functors Arithmetic Function Object Classes + * @ingroup functors + * + * The library provides function objects for basic arithmetic operations. + * See the documentation for @link functors function objects @endlink + * for examples of their use. + * + * @{ + */ + +#if __glibcxx_transparent_operators // C++ >= 14 + struct __is_transparent; // undefined + + template + struct plus; + + template + struct minus; + + template + struct multiplies; + + template + struct divides; + + template + struct modulus; + + template + struct negate; +#endif + +// Ignore warnings about unary_function and binary_function. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct plus : public binary_function<_Tp, _Tp, _Tp> + { + /// Returns the sum + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x + __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct minus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x - __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct multiplies : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct divides : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x / __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct modulus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x % __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct negate : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return -__x; } + }; +#pragma GCC diagnostic pop + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + template<> + struct plus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) + std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct minus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) - std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct multiplies + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) * std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct divides + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) / std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct modulus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) % std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct negate + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(-std::forward<_Tp>(__t))) + -> decltype(-std::forward<_Tp>(__t)) + { return -std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + /** @} */ + + // 20.3.3 comparisons + /** @defgroup comparison_functors Comparison Classes + * @ingroup functors + * + * The library provides six wrapper functors for all the basic comparisons + * in C++, like @c <. + * + * @{ + */ +#if __glibcxx_transparent_operators // C++ >= 14 + template + struct equal_to; + + template + struct not_equal_to; + + template + struct greater; + + template + struct less; + + template + struct greater_equal; + + template + struct less_equal; +#endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct not_equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x >= __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x <= __y; } + }; + + // Partial specialization of std::greater for pointers. + template + struct greater<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L + if (std::__is_constant_evaluated()) + return __x > __y; +#endif + return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less for pointers. + template + struct less<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L + if (std::__is_constant_evaluated()) + return __x < __y; +#endif + return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::greater_equal for pointers. + template + struct greater_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L + if (std::__is_constant_evaluated()) + return __x >= __y; +#endif + return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less_equal for pointers. + template + struct less_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L + if (std::__is_constant_evaluated()) + return __x <= __y; +#endif + return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y; + } + }; +#pragma GCC diagnostic pop + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct not_equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) != std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) > std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator> member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator> for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) < std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator< member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator< for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator>= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator>= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator<= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator<= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; +#endif // __glibcxx_transparent_operators + /** @} */ + + // 20.3.4 logical operations + /** @defgroup logical_functors Boolean Operations Classes + * @ingroup functors + * + * The library provides function objects for the logical operations: + * `&&`, `||`, and `!`. + * + * @{ + */ +#ifdef __glibcxx_transparent_operators // C++ >= 14 + template + struct logical_and; + + template + struct logical_or; + + template + struct logical_not; +#endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_and : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x && __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_or : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x || __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_not : public unary_function<_Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x) const + { return !__x; } + }; +#pragma GCC diagnostic pop + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) && std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) || std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(!std::forward<_Tp>(__t))) + -> decltype(!std::forward<_Tp>(__t)) + { return !std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif // __glibcxx_transparent_operators + /** @} */ + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + template + struct bit_and; + + template + struct bit_or; + + template + struct bit_xor; + + template + struct bit_not; +#endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 660. Missing Bitwise Operations. + template + struct bit_and : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x & __y; } + }; + + template + struct bit_or : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x | __y; } + }; + + template + struct bit_xor : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x ^ __y; } + }; + + template + struct bit_not : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return ~__x; } + }; +#pragma GCC diagnostic pop + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + template <> + struct bit_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) & std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) | std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_xor + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(~std::forward<_Tp>(__t))) + -> decltype(~std::forward<_Tp>(__t)) + { return ~std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif // C++14 + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + // 20.3.5 negators + /** @defgroup negators Negators + * @ingroup functors + * + * The function templates `not1` and `not2` are function object adaptors, + * which each take a predicate functor and wrap it in an instance of + * `unary_negate` or `binary_negate`, respectively. Those classes are + * functors whose `operator()` evaluates the wrapped predicate function + * and then returns the negation of the result. + * + * For example, given a vector of integers and a trivial predicate, + * \code + * struct IntGreaterThanThree + * : public std::unary_function + * { + * bool operator() (int x) const { return x > 3; } + * }; + * + * std::find_if (v.begin(), v.end(), not1(IntGreaterThanThree())); + * \endcode + * The call to `find_if` will locate the first index (i) of `v` for which + * `!(v[i] > 3)` is true. + * + * The not1/unary_negate combination works on predicates taking a single + * argument. The not2/binary_negate combination works on predicates taking + * two arguments. + * + * @deprecated Deprecated in C++17, no longer in the standard since C++20. + * Use `not_fn` instead. + * + * @{ + */ + /// One of the @link negators negation functors@endlink. + template + class _GLIBCXX17_DEPRECATED unary_negate + : public unary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + unary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::argument_type& __x) const + { return !_M_pred(__x); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX17_DEPRECATED_SUGGEST("std::not_fn") + _GLIBCXX14_CONSTEXPR + inline unary_negate<_Predicate> + not1(const _Predicate& __pred) + { return unary_negate<_Predicate>(__pred); } + + /// One of the @link negators negation functors@endlink. + template + class _GLIBCXX17_DEPRECATED binary_negate + : public binary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + binary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::first_argument_type& __x, + const typename _Predicate::second_argument_type& __y) const + { return !_M_pred(__x, __y); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX17_DEPRECATED_SUGGEST("std::not_fn") + _GLIBCXX14_CONSTEXPR + inline binary_negate<_Predicate> + not2(const _Predicate& __pred) + { return binary_negate<_Predicate>(__pred); } + /** @} */ + + // 20.3.7 adaptors pointers functions + /** @defgroup pointer_adaptors Adaptors for pointers to functions + * @ingroup functors + * + * The advantage of function objects over pointers to functions is that + * the objects in the standard library declare nested typedefs describing + * their argument and result types with uniform names (e.g., `result_type` + * from the base classes `unary_function` and `binary_function`). + * Sometimes those typedefs are required, not just optional. + * + * Adaptors are provided to turn pointers to unary (single-argument) and + * binary (double-argument) functions into function objects. The + * long-winded functor `pointer_to_unary_function` is constructed with a + * function pointer `f`, and its `operator()` called with argument `x` + * returns `f(x)`. The functor `pointer_to_binary_function` does the same + * thing, but with a double-argument `f` and `operator()`. + * + * The function `ptr_fun` takes a pointer-to-function `f` and constructs + * an instance of the appropriate functor. + * + * @deprecated Deprecated in C++11, no longer in the standard since C++17. + * + * @{ + */ + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_unary_function : public unary_function<_Arg, _Result> + { + protected: + _Result (*_M_ptr)(_Arg); + + public: + pointer_to_unary_function() { } + + explicit + pointer_to_unary_function(_Result (*__x)(_Arg)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg __x) const + { return _M_ptr(__x); } + } _GLIBCXX11_DEPRECATED; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::function") + inline pointer_to_unary_function<_Arg, _Result> + ptr_fun(_Result (*__x)(_Arg)) + { return pointer_to_unary_function<_Arg, _Result>(__x); } + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_binary_function + : public binary_function<_Arg1, _Arg2, _Result> + { + protected: + _Result (*_M_ptr)(_Arg1, _Arg2); + + public: + pointer_to_binary_function() { } + + explicit + pointer_to_binary_function(_Result (*__x)(_Arg1, _Arg2)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg1 __x, _Arg2 __y) const + { return _M_ptr(__x, __y); } + } _GLIBCXX11_DEPRECATED; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::function") + inline pointer_to_binary_function<_Arg1, _Arg2, _Result> + ptr_fun(_Result (*__x)(_Arg1, _Arg2)) + { return pointer_to_binary_function<_Arg1, _Arg2, _Result>(__x); } + /** @} */ + + template + struct _Identity + : public unary_function<_Tp, _Tp> + { + _Tp& + operator()(_Tp& __x) const + { return __x; } + + const _Tp& + operator()(const _Tp& __x) const + { return __x; } + }; + + // Partial specialization, avoids confusing errors in e.g. std::set. + template struct _Identity : _Identity<_Tp> { }; + + template + struct _Select1st + : public unary_function<_Pair, typename _Pair::first_type> + { + typename _Pair::first_type& + operator()(_Pair& __x) const + { return __x.first; } + + const typename _Pair::first_type& + operator()(const _Pair& __x) const + { return __x.first; } + +#if __cplusplus >= 201103L + template + typename _Pair2::first_type& + operator()(_Pair2& __x) const + { return __x.first; } + + template + const typename _Pair2::first_type& + operator()(const _Pair2& __x) const + { return __x.first; } +#endif + }; + + template + struct _Select2nd + : public unary_function<_Pair, typename _Pair::second_type> + { + typename _Pair::second_type& + operator()(_Pair& __x) const + { return __x.second; } + + const typename _Pair::second_type& + operator()(const _Pair& __x) const + { return __x.second; } + }; + + // 20.3.8 adaptors pointers members + /** @defgroup ptrmem_adaptors Adaptors for pointers to members + * @ingroup functors + * + * There are a total of 8 = 2^3 function objects in this family. + * (1) Member functions taking no arguments vs member functions taking + * one argument. + * (2) Call through pointer vs call through reference. + * (3) Const vs non-const member function. + * + * All of this complexity is in the function objects themselves. You can + * ignore it by using the helper function `mem_fun` and `mem_fun_ref`, + * which create whichever type of adaptor is appropriate. + * + * @deprecated Deprecated in C++11, no longer in the standard since C++17. + * Use `mem_fn` instead. + * + * @{ + */ + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class mem_fun_t : public unary_function<_Tp*, _Ret> + { + public: + explicit + mem_fun_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class const_mem_fun_t : public unary_function + { + public: + explicit + const_mem_fun_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + mem_fun_ref_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class const_mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class mem_fun1_t : public binary_function<_Tp*, _Arg, _Ret> + { + public: + explicit + mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class const_mem_fun1_t : public binary_function + { + public: + explicit + const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + } _GLIBCXX11_DEPRECATED; + + /// One of the @link ptrmem_adaptors adaptors for member pointers@endlink. + template + class const_mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + } _GLIBCXX11_DEPRECATED; + + // Mem_fun adaptor helper functions. There are only two: + // mem_fun and mem_fun_ref. + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)()) + { return mem_fun_t<_Ret, _Tp>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline const_mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)() const) + { return const_mem_fun_t<_Ret, _Tp>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)()) + { return mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline const_mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)() const) + { return const_mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline const_mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + template + _GLIBCXX11_DEPRECATED_SUGGEST("std::mem_fn") + inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } +#pragma GCC diagnostic pop + + /** @} */ + +#ifdef __glibcxx_transparent_operators // C++ >= 14 + template> + struct __has_is_transparent + { }; + + template + struct __has_is_transparent<_Func, _SfinaeType, + __void_t> + { typedef void type; }; + + template + using __has_is_transparent_t + = typename __has_is_transparent<_Func, _SfinaeType>::type; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED +# include +#endif + +#endif /* _STL_FUNCTION_H */ diff --git a/template/sysroot/include/bits/stl_heap.h b/template/sysroot/include/bits/stl_heap.h new file mode 100644 index 0000000..9c1214a --- /dev/null +++ b/template/sysroot/include/bits/stl_heap.h @@ -0,0 +1,584 @@ +// Heap implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_heap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{queue} + */ + +#ifndef _STL_HEAP_H +#define _STL_HEAP_H 1 + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup heap_algorithms Heap + * @ingroup sorting_algorithms + */ + + template + _GLIBCXX20_CONSTEXPR + _Distance + __is_heap_until(_RandomAccessIterator __first, _Distance __n, + _Compare& __comp) + { + _Distance __parent = 0; + for (_Distance __child = 1; __child < __n; ++__child) + { + if (__comp(__first + __parent, __first + __child)) + return __child; + if ((__child & 1) == 0) + ++__parent; + } + return __n; + } + + // __is_heap, a predicate testing whether or not a range is a heap. + // This function is an extension, not part of the C++ standard. + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Distance __n) + { + __gnu_cxx::__ops::_Iter_less_iter __comp; + return std::__is_heap_until(__first, __n, __comp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __n, __cmp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::__is_heap(__first, std::distance(__first, __last)); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + return std::__is_heap(__first, _GLIBCXX_MOVE(__comp), + std::distance(__first, __last)); + } + + // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap, + // + is_heap and is_heap_until in C++0x. + + template + _GLIBCXX20_CONSTEXPR + void + __push_heap(_RandomAccessIterator __first, + _Distance __holeIndex, _Distance __topIndex, _Tp __value, + _Compare& __comp) + { + _Distance __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) + { + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent)); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = _GLIBCXX_MOVE(__value); + } + + /** + * @brief Push an element onto a heap. + * @param __first Start of heap. + * @param __last End of heap + element. + * @ingroup heap_algorithms + * + * This operation pushes the element at last-1 onto the valid heap + * over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last - 1); + + __gnu_cxx::__ops::_Iter_less_val __comp; + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Push an element onto a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap + element. + * @param __comp Comparison functor. + * @ingroup heap_algorithms + * + * This operation pushes the element at __last-1 onto the valid + * heap over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. Compare operations are + * performed using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last - 1, __comp); + + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __len, _Tp __value, _Compare __comp) + { + const _Distance __topIndex = __holeIndex; + _Distance __secondChild = __holeIndex; + while (__secondChild < (__len - 1) / 2) + { + __secondChild = 2 * (__secondChild + 1); + if (__comp(__first + __secondChild, + __first + (__secondChild - 1))) + __secondChild--; + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild)); + __holeIndex = __secondChild; + } + if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2) + { + __secondChild = 2 * (__secondChild + 1); + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + + (__secondChild - 1))); + __holeIndex = __secondChild - 1; + } + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + std::__push_heap(__first, __holeIndex, __topIndex, + _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _RandomAccessIterator __result, _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + _ValueType __value = _GLIBCXX_MOVE(*__result); + *__result = _GLIBCXX_MOVE(*__first); + std::__adjust_heap(__first, _DistanceType(0), + _DistanceType(__last - __first), + _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Pop an element off a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @pre [__first, __last) is a valid, non-empty range. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + if (__last - __first > 1) + { + --__last; + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Pop an element off a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. Comparisons are made using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + if (__last - __first > 1) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + --__last; + std::__pop_heap(__first, __last, __last, __cmp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + if (__last - __first < 2) + return; + + const _DistanceType __len = __last - __first; + _DistanceType __parent = (__len - 2) / 2; + while (true) + { + _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent)); + std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value), + __comp); + if (__parent == 0) + return; + __parent--; + } + } + + /** + * @brief Construct a heap over a range. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__make_heap(__first, __last, __comp); + } + + /** + * @brief Construct a heap over a range using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__make_heap(__first, __last, __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + while (__last - __first > 1) + { + --__last; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Sort a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__sort_heap(__first, __last, __comp); + } + + /** + * @brief Sort a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__sort_heap(__first, __last, __cmp); + } + +#if __cplusplus >= 201103L + /** + * @brief Search the end of a heap. + * @param __first Start of range. + * @param __last End of range. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __comp); + } + + /** + * @brief Search the end of a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. Comparisons are made using __comp. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); + } + + /** + * @brief Determines whether a range is a heap. + * @param __first Start of range. + * @param __last End of range. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::is_heap_until(__first, __last) == __last; } + + /** + * @brief Determines whether a range is a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + const auto __dist = std::distance(__first, __last); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __dist, __cmp) == __dist; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_HEAP_H */ diff --git a/template/sysroot/include/bits/stl_iterator.h b/template/sysroot/include/bits/stl_iterator.h new file mode 100644 index 0000000..560a10a --- /dev/null +++ b/template/sysroot/include/bits/stl_iterator.h @@ -0,0 +1,3015 @@ +// Iterators -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file implements reverse_iterator, back_insert_iterator, + * front_insert_iterator, insert_iterator, __normal_iterator, and their + * supporting functions and overloaded operators. + */ + +#ifndef _STL_ITERATOR_H +#define _STL_ITERATOR_H 1 + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +#endif + +#if __cplusplus >= 202002L +# include +# include +# include +# include +# include +#endif + +#if __glibcxx_tuple_like // >= C++23 +# include // for tuple_element_t +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup iterators + * @{ + */ + +#if __glibcxx_concepts + namespace __detail + { + // Weaken iterator_category _Cat to _Limit if it is derived from that, + // otherwise use _Otherwise. + template + using __clamp_iter_cat + = __conditional_t, _Limit, _Otherwise>; + } +#endif + +// Ignore warnings about std::iterator. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + // 24.4.1 Reverse iterators + /** + * Bidirectional and random access iterators have corresponding reverse + * %iterator adaptors that iterate through the data structure in the + * opposite direction. They have the same signatures as the corresponding + * iterators. The fundamental relation between a reverse %iterator and its + * corresponding %iterator @c i is established by the identity: + * @code + * &*(reverse_iterator(i)) == &*(i - 1) + * @endcode + * + * This mapping is dictated by the fact that while there is always a + * pointer past the end of an array, there might not be a valid pointer + * before the beginning of an array. [24.4.1]/1,2 + * + * Reverse iterators can be tricky and surprising at first. Their + * semantics make sense, however, and the trickiness is a side effect of + * the requirement that the iterators must be safe. + */ + template + class reverse_iterator + : public iterator::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + template + friend class reverse_iterator; + +#if __glibcxx_concepts + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3435. three_way_comparable_with, [...]> + template + static constexpr bool __convertible = !is_same_v<_Iter, _Iterator> + && convertible_to; +#endif + + protected: + _Iterator current; + + typedef iterator_traits<_Iterator> __traits_type; + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::pointer pointer; +#if ! __glibcxx_concepts + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::reference reference; +#else + using iterator_concept + = __conditional_t, + random_access_iterator_tag, + bidirectional_iterator_tag>; + using iterator_category + = __detail::__clamp_iter_cat; + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + using reference = iter_reference_t<_Iterator>; +#endif + + /** + * The default constructor value-initializes member @p current. + * If it is a pointer, that means it is zero-initialized. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 235 No specification of default ctor for reverse_iterator + // 1012. reverse_iterator default ctor should value initialize + _GLIBCXX17_CONSTEXPR + reverse_iterator() + _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator())) + : current() + { } + + /** + * This %iterator will move in the opposite direction that @p x does. + */ + explicit _GLIBCXX17_CONSTEXPR + reverse_iterator(iterator_type __x) + _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x))) + : current(__x) + { } + + /** + * The copy constructor is normal. + */ + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator& __x) + _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current))) + : current(__x.current) + { } + +#if __cplusplus >= 201103L + reverse_iterator& operator=(const reverse_iterator&) = default; +#endif + + /** + * A %reverse_iterator across other types can be copied if the + * underlying %iterator can be converted to the type of @c current. + */ + template +#if __glibcxx_concepts + requires __convertible<_Iter> +#endif + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator<_Iter>& __x) + _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current))) + : current(__x.current) + { } + +#if __cplusplus >= 201103L + template +#if __glibcxx_concepts + requires __convertible<_Iter> + && assignable_from<_Iterator&, const _Iter&> +#endif + _GLIBCXX17_CONSTEXPR + reverse_iterator& + operator=(const reverse_iterator<_Iter>& __x) + _GLIBCXX_NOEXCEPT_IF(noexcept(current = __x.current)) + { + current = __x.current; + return *this; + } +#endif + + /** + * @return @c current, the %iterator used for underlying work. + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR iterator_type + base() const + _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(current))) + { return current; } + + /** + * @return A reference to the value at @c --current + * + * This requires that @c --current is dereferenceable. + * + * @warning This implementation requires that for an iterator of the + * underlying iterator type, @c x, a reference obtained by + * @c *x remains valid after @c x has been modified or + * destroyed. This is a bug: http://gcc.gnu.org/PR51823 + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + + /** + * @return A pointer to the value at @c --current + * + * This requires that @c --current is dereferenceable. + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR pointer + operator->() const +#if __cplusplus > 201703L && __cpp_concepts >= 201907L + requires is_pointer_v<_Iterator> + || requires(const _Iterator __i) { __i.operator->(); } +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1052. operator-> should also support smart pointers + _Iterator __tmp = current; + --__tmp; + return _S_to_pointer(__tmp); + } + + /** + * @return @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator++() + { + --current; + return *this; + } + + /** + * @return The original value of @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + + /** + * @return @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator--() + { + ++current; + return *this; + } + + /** + * @return A reverse_iterator with the previous value of @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + + /** + * @return *this + * + * Moves the underlying iterator backwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + + /** + * @return *this + * + * Moves the underlying iterator forwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + + /** + * @return The value at @c current - @a __n - 1 + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX_NODISCARD + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const + { return *(*this + __n); } + +#if __cplusplus > 201703L && __glibcxx_concepts + [[nodiscard]] + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && noexcept(ranges::iter_move(--std::declval<_Iterator&>()))) + { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + + template _Iter2> + friend constexpr void + iter_swap(const reverse_iterator& __x, + const reverse_iterator<_Iter2>& __y) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && is_nothrow_copy_constructible_v<_Iter2> + && noexcept(ranges::iter_swap(--std::declval<_Iterator&>(), + --std::declval<_Iter2&>()))) + { + auto __xtmp = __x.base(); + auto __ytmp = __y.base(); + ranges::iter_swap(--__xtmp, --__ytmp); + } +#endif + + private: + template + static _GLIBCXX17_CONSTEXPR _Tp* + _S_to_pointer(_Tp* __p) + { return __p; } + + template + static _GLIBCXX17_CONSTEXPR pointer + _S_to_pointer(_Tp __t) + { return __t.operator->(); } + }; + + ///@{ + /** + * @param __x A %reverse_iterator. + * @param __y A %reverse_iterator. + * @return A simple bool. + * + * Reverse iterators forward comparisons to their underlying base() + * iterators. + * + */ +#if __cplusplus <= 201703L || ! defined __glibcxx_concepts + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() < __x.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y < __x; } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x < __y); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 280. Comparison of reverse_iterator to const reverse_iterator. + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() == __y.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() > __y.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() != __y.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() < __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() >= __y.base(); } + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() <= __y.base(); } +#else // C++20 + template + [[nodiscard]] + constexpr bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() == __y.base() } -> convertible_to; } + { return __x.base() == __y.base(); } + + template + [[nodiscard]] + constexpr bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() != __y.base() } -> convertible_to; } + { return __x.base() != __y.base(); } + + template + [[nodiscard]] + constexpr bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() > __y.base() } -> convertible_to; } + { return __x.base() > __y.base(); } + + template + [[nodiscard]] + constexpr bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() < __y.base() } -> convertible_to; } + { return __x.base() < __y.base(); } + + template + [[nodiscard]] + constexpr bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() >= __y.base() } -> convertible_to; } + { return __x.base() >= __y.base(); } + + template + [[nodiscard]] + constexpr bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() <= __y.base() } -> convertible_to; } + { return __x.base() <= __y.base(); } + + template _IteratorR> + [[nodiscard]] + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() <=> __x.base(); } + + // Additional, non-standard overloads to avoid ambiguities with greedy, + // unconstrained overloads in associated namespaces. + + template + [[nodiscard]] + constexpr bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + requires requires { { __x.base() == __y.base() } -> convertible_to; } + { return __x.base() == __y.base(); } + + template + [[nodiscard]] + constexpr compare_three_way_result_t<_Iterator, _Iterator> + operator<=>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() <=> __x.base(); } +#endif // C++20 + ///@} + +#if __cplusplus < 201103L + template + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } + + template + inline typename reverse_iterator<_IteratorL>::difference_type + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() - __x.base(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 685. reverse_iterator/move_iterator difference has invalid signatures + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR auto + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + -> decltype(__y.base() - __x.base()) + { return __y.base() - __x.base(); } +#endif + + template + _GLIBCXX_NODISCARD + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } + +#if __cplusplus >= 201103L + // Same as C++14 make_reverse_iterator but used in C++11 mode too. + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + __make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# ifdef __glibcxx_make_reverse_iterator // C++ >= 14 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2285. make_reverse_iterator + /// Generator function for reverse_iterator. + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# if __cplusplus > 201703L && defined __glibcxx_concepts + template + requires (!sized_sentinel_for<_Iterator1, _Iterator2>) + inline constexpr bool + disable_sized_sentinel_for, + reverse_iterator<_Iterator2>> = true; +# endif // C++20 +# endif // __glibcxx_make_reverse_iterator + + template + _GLIBCXX20_CONSTEXPR + auto + __niter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__niter_base(__it.base()))) + { return __make_reverse_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + : __is_move_iterator<_Iterator> + { }; + + template + _GLIBCXX20_CONSTEXPR + auto + __miter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__miter_base(__it.base()))) + { return __make_reverse_iterator(__miter_base(__it.base())); } +#endif // C++11 + + // 24.4.2.2.1 back_insert_iterator + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator appends it to the container using + * push_back. + * + * Tip: Using the back_inserter function to create these iterators can + * save typing. + */ + template + class back_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + back_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the end, if you like). Assigning a value to the %iterator will + * always append the value to the end of the container. + */ +#if __cplusplus < 201103L + back_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_back(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_back(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_back(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of back_insert_iterator working on @p __x. + * + * This wrapper function helps in creating back_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline back_insert_iterator<_Container> + back_inserter(_Container& __x) + { return back_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator prepends it to the container using + * push_front. + * + * Tip: Using the front_inserter function to create these iterators can + * save typing. + */ + template + class front_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + front_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the front, if you like). Assigning a value to the %iterator will + * always prepend the value to the front of the container. + */ +#if __cplusplus < 201103L + front_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_front(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_front(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_front(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of front_insert_iterator working on @p x. + * + * This wrapper function helps in creating front_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline front_insert_iterator<_Container> + front_inserter(_Container& __x) + { return front_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator inserts it in the container at the + * %iterator's position, rather than overwriting the value at that + * position. + * + * (Sequences will actually insert a @e copy of the value before the + * %iterator's position.) + * + * Tip: Using the inserter function to create these iterators can + * save typing. + */ + template + class insert_iterator + : public iterator + { +#if __cplusplus > 201703L && defined __glibcxx_concepts + using _Iter = std::__detail::__range_iter_t<_Container>; +#else + typedef typename _Container::iterator _Iter; +#endif + protected: + _Container* container; + _Iter iter; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + +#if __cplusplus > 201703L && defined __glibcxx_concepts + using difference_type = ptrdiff_t; +#endif + + /** + * The only way to create this %iterator is with a container and an + * initial position (a normal %iterator into the container). + */ + _GLIBCXX20_CONSTEXPR + insert_iterator(_Container& __x, _Iter __i) + : container(std::__addressof(__x)), iter(__i) {} + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator maintains its own position in the + * container. Assigning a value to the %iterator will insert the + * value into the container at the place before the %iterator. + * + * The position is maintained such that subsequent assignments will + * insert values immediately after one another. For example, + * @code + * // vector v contains A and Z + * + * insert_iterator i (v, ++v.begin()); + * i = 1; + * i = 2; + * i = 3; + * + * // vector v contains A, 1, 2, 3, and Z + * @endcode + */ +#if __cplusplus < 201103L + insert_iterator& + operator=(typename _Container::const_reference __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(const typename _Container::value_type& __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } + + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(typename _Container::value_type&& __value) + { + iter = container->insert(iter, std::move(__value)); + ++iter; + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++(int) + { return *this; } + }; + +#pragma GCC diagnostic pop + + /** + * @param __x A container of arbitrary type. + * @param __i An iterator into the container. + * @return An instance of insert_iterator working on @p __x. + * + * This wrapper function helps in creating insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ +#if __cplusplus > 201703L && defined __glibcxx_concepts + template + [[nodiscard]] + constexpr insert_iterator<_Container> + inserter(_Container& __x, std::__detail::__range_iter_t<_Container> __i) + { return insert_iterator<_Container>(__x, __i); } +#else + template + _GLIBCXX_NODISCARD + inline insert_iterator<_Container> + inserter(_Container& __x, typename _Container::iterator __i) + { return insert_iterator<_Container>(__x, __i); } +#endif + + /// @} group iterators + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // This iterator adapter is @a normal in the sense that it does not + // change the semantics of any of the operators of its iterator + // parameter. Its primary purpose is to convert an iterator that is + // not a class, e.g. a pointer, into an iterator that is a class. + // The _Container parameter exists solely so that different containers + // using this template can instantiate different types, even if the + // _Iterator parameter is the same. + template + class __normal_iterator + { + protected: + _Iterator _M_current; + + typedef std::iterator_traits<_Iterator> __traits_type; + +#if __cplusplus >= 201103L + template + using __convertible_from + = std::__enable_if_t::value>; +#endif + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::reference reference; + typedef typename __traits_type::pointer pointer; + +#if __cplusplus > 201703L && __glibcxx_concepts + using iterator_concept = std::__detail::__iter_concept<_Iterator>; +#endif + + _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT + : _M_current(_Iterator()) { } + + explicit _GLIBCXX20_CONSTEXPR + __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT + : _M_current(__i) { } + + // Allow iterator to const_iterator conversion +#if __cplusplus >= 201103L + template> + _GLIBCXX20_CONSTEXPR + __normal_iterator(const __normal_iterator<_Iter, _Container>& __i) + noexcept +#else + // N.B. _Container::pointer is not actually in container requirements, + // but is present in std::vector and std::basic_string. + template + __normal_iterator(const __normal_iterator<_Iter, + typename __enable_if< + (std::__are_same<_Iter, typename _Container::pointer>::__value), + _Container>::__type>& __i) +#endif + : _M_current(__i.base()) { } + + // Forward iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *_M_current; } + + _GLIBCXX20_CONSTEXPR + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return _M_current; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator++() _GLIBCXX_NOEXCEPT + { + ++_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator++(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current++); } + + // Bidirectional iterator requirements + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator--() _GLIBCXX_NOEXCEPT + { + --_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator--(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current--); } + + // Random access iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT + { return _M_current[__n]; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current += __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator+(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current + __n); } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current -= __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator-(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current - __n); } + + _GLIBCXX20_CONSTEXPR + const _Iterator& + base() const _GLIBCXX_NOEXCEPT + { return _M_current; } + }; + + // Note: In what follows, the left- and right-hand-side iterators are + // allowed to vary in types (conceptually in cv-qualification) so that + // comparison between cv-qualified and non-cv-qualified iterators be + // valid. However, the greedy and unfriendly operators in std::rel_ops + // will make overload resolution ambiguous (when in scope) if we don't + // provide overloads whose operands are of the same type. Can someone + // remind me what generic programming is about? -- Gaby + +#if __cpp_lib_three_way_comparison + template + [[nodiscard]] + constexpr bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + requires requires { + { __lhs.base() == __rhs.base() } -> std::convertible_to; + } + { return __lhs.base() == __rhs.base(); } + + template + [[nodiscard]] + constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> + operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } + + template + [[nodiscard]] + constexpr bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + requires requires { + { __lhs.base() == __rhs.base() } -> std::convertible_to; + } + { return __lhs.base() == __rhs.base(); } + + template + [[nodiscard]] + constexpr std::__detail::__synth3way_t<_Iterator> + operator<=>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } +#else + // Forward iterator requirements + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + // Random access iterator requirements + template + _GLIBCXX_NODISCARD + inline bool + operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + _GLIBCXX_NODISCARD + inline bool + operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + _GLIBCXX_NODISCARD + inline bool + operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + _GLIBCXX_NODISCARD + inline bool + operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } +#endif // three-way comparison + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template +#if __cplusplus >= 201103L + // DR 685. + [[__nodiscard__]] _GLIBCXX20_CONSTEXPR + inline auto + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept + -> decltype(__lhs.base() - __rhs.base()) +#else + inline typename __normal_iterator<_IteratorL, _Container>::difference_type + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) +#endif + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline typename __normal_iterator<_Iterator, _Container>::difference_type + operator-(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + inline __normal_iterator<_Iterator, _Container> + operator+(typename __normal_iterator<_Iterator, _Container>::difference_type + __n, const __normal_iterator<_Iterator, _Container>& __i) + _GLIBCXX_NOEXCEPT + { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + _GLIBCXX20_CONSTEXPR + _Iterator + __niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it.base(); } + +#if __cplusplus >= 201103L + +#if __cplusplus <= 201703L + // Need to overload __to_address because the pointer_traits primary template + // will deduce element_type of __normal_iterator as T* rather than T. + template + constexpr auto + __to_address(const __gnu_cxx::__normal_iterator<_Iterator, + _Container>& __it) noexcept + -> decltype(std::__to_address(__it.base())) + { return std::__to_address(__it.base()); } +#endif + + /** + * @addtogroup iterators + * @{ + */ + +#if __cplusplus > 201703L && __glibcxx_concepts + template + class move_sentinel + { + public: + constexpr + move_sentinel() + noexcept(is_nothrow_default_constructible_v<_Sent>) + : _M_last() { } + + constexpr explicit + move_sentinel(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_last(std::move(__s)) { } + + template requires convertible_to + constexpr + move_sentinel(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_constructible_v<_Sent, const _S2&>) + : _M_last(__s.base()) + { } + + template requires assignable_from<_Sent&, const _S2&> + constexpr move_sentinel& + operator=(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_assignable_v<_Sent, const _S2&>) + { + _M_last = __s.base(); + return *this; + } + + [[nodiscard]] + constexpr _Sent + base() const + noexcept(is_nothrow_copy_constructible_v<_Sent>) + { return _M_last; } + + private: + _Sent _M_last; + }; +#endif // C++20 + + namespace __detail + { +#if __cplusplus > 201703L && __glibcxx_concepts + template + struct __move_iter_cat + { }; + + template + requires requires { typename __iter_category_t<_Iterator>; } + struct __move_iter_cat<_Iterator> + { + using iterator_category + = __clamp_iter_cat<__iter_category_t<_Iterator>, + random_access_iterator_tag>; + }; +#endif + } + + // 24.4.3 Move iterators + /** + * Class template move_iterator is an iterator adapter with the same + * behavior as the underlying iterator except that its dereference + * operator implicitly converts the value returned by the underlying + * iterator's dereference operator to an rvalue reference. Some + * generic algorithms can be called with move iterators to replace + * copying with moving. + */ + template + class move_iterator +#if __cplusplus > 201703L && __glibcxx_concepts + : public __detail::__move_iter_cat<_Iterator> +#endif + { + _Iterator _M_current; + + using __traits_type = iterator_traits<_Iterator>; +#if ! (__cplusplus > 201703L && __glibcxx_concepts) + using __base_ref = typename __traits_type::reference; +#endif + + template + friend class move_iterator; + +#if __glibcxx_concepts // C++20 && concepts + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3435. three_way_comparable_with, [...]> + template + static constexpr bool __convertible = !is_same_v<_Iter2, _Iterator> + && convertible_to; +#endif + +#if __cplusplus > 201703L && __glibcxx_concepts + static auto + _S_iter_concept() + { + if constexpr (random_access_iterator<_Iterator>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_iterator<_Iterator>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_iterator<_Iterator>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } +#endif + + public: + using iterator_type = _Iterator; + +#ifdef __glibcxx_move_iterator_concept // C++ >= 20 && lib_concepts + using iterator_concept = decltype(_S_iter_concept()); + + // iterator_category defined in __move_iter_cat + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + using pointer = _Iterator; + using reference = iter_rvalue_reference_t<_Iterator>; +#else + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + // NB: DR 680. + typedef _Iterator pointer; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2106. move_iterator wrapping iterators returning prvalues + using reference + = __conditional_t::value, + typename remove_reference<__base_ref>::type&&, + __base_ref>; +#endif + + _GLIBCXX17_CONSTEXPR + move_iterator() + : _M_current() { } + + explicit _GLIBCXX17_CONSTEXPR + move_iterator(iterator_type __i) + : _M_current(std::move(__i)) { } + + template +#if __glibcxx_concepts + requires __convertible<_Iter> +#endif + _GLIBCXX17_CONSTEXPR + move_iterator(const move_iterator<_Iter>& __i) + : _M_current(__i._M_current) { } + + template +#if __glibcxx_concepts + requires __convertible<_Iter> + && assignable_from<_Iterator&, const _Iter&> +#endif + _GLIBCXX17_CONSTEXPR + move_iterator& operator=(const move_iterator<_Iter>& __i) + { + _M_current = __i._M_current; + return *this; + } + +#if __cplusplus <= 201703L + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR iterator_type + base() const + { return _M_current; } +#else + [[nodiscard]] + constexpr const iterator_type& + base() const & noexcept + { return _M_current; } + + [[nodiscard]] + constexpr iterator_type + base() && + { return std::move(_M_current); } +#endif + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR reference + operator*() const +#if __cplusplus > 201703L && __glibcxx_concepts + { return ranges::iter_move(_M_current); } +#else + { return static_cast(*_M_current); } +#endif + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR pointer + operator->() const + { return _M_current; } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator++() + { + ++_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator++(int) + { + move_iterator __tmp = *this; + ++_M_current; + return __tmp; + } + +#if __glibcxx_concepts + constexpr void + operator++(int) requires (!forward_iterator<_Iterator>) + { ++_M_current; } +#endif + + _GLIBCXX17_CONSTEXPR move_iterator& + operator--() + { + --_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator--(int) + { + move_iterator __tmp = *this; + --_M_current; + return __tmp; + } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR move_iterator + operator+(difference_type __n) const + { return move_iterator(_M_current + __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator+=(difference_type __n) + { + _M_current += __n; + return *this; + } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR move_iterator + operator-(difference_type __n) const + { return move_iterator(_M_current - __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator-=(difference_type __n) + { + _M_current -= __n; + return *this; + } + + [[__nodiscard__]] + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const +#if __cplusplus > 201703L && __glibcxx_concepts + { return ranges::iter_move(_M_current + __n); } +#else + { return std::move(_M_current[__n]); } +#endif + +#if __cplusplus > 201703L && __glibcxx_concepts + template _Sent> + [[nodiscard]] + friend constexpr bool + operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() == __y.base(); } + + template _Sent> + [[nodiscard]] + friend constexpr iter_difference_t<_Iterator> + operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) + { return __x.base() - __y.base(); } + + template _Sent> + [[nodiscard]] + friend constexpr iter_difference_t<_Iterator> + operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() - __y.base(); } + + [[nodiscard]] + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const move_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + template _Iter2> + friend constexpr void + iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { return ranges::iter_swap(__x._M_current, __y._M_current); } +#endif // C++20 + }; + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __glibcxx_concepts + requires requires { { __x.base() == __y.base() } -> convertible_to; } +#endif + { return __x.base() == __y.base(); } + +#if __cpp_lib_three_way_comparison + template _IteratorR> + [[__nodiscard__]] + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return __x.base() <=> __y.base(); } +#else + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return !(__x == __y); } +#endif + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __glibcxx_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return __x.base() < __y.base(); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __glibcxx_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return !(__y < __x); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __glibcxx_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return __y < __x; } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __glibcxx_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return !(__x < __y); } + + // Note: See __normal_iterator operators note from Gaby to understand + // why we have these extra overloads for some move_iterator operators. + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + +#if __cpp_lib_three_way_comparison + template + [[__nodiscard__]] + constexpr compare_three_way_result_t<_Iterator> + operator<=>(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() <=> __y.base(); } +#else + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() < __y.base(); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __y < __x; } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x < __y); } +#endif // ! C++20 + + // DR 685. + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR auto + operator-(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + -> decltype(__x.base() - __y.base()) + { return __x.base() - __y.base(); } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + operator+(typename move_iterator<_Iterator>::difference_type __n, + const move_iterator<_Iterator>& __x) + { return __x + __n; } + + template + [[__nodiscard__]] + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + make_move_iterator(_Iterator __i) + { return move_iterator<_Iterator>(std::move(__i)); } + + template::value_type>::value, + _Iterator, move_iterator<_Iterator>>> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Iterator __i) + { return _ReturnType(__i); } + + // Overload for pointers that matches std::move_if_noexcept more closely, + // returning a constant iterator when we don't want to move. + template::value, + const _Tp*, move_iterator<_Tp*>>> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Tp* __i) + { return _ReturnType(__i); } + +#if __cplusplus > 201703L && __glibcxx_concepts + // [iterators.common] Common iterators + + namespace __detail + { + template + concept __common_iter_has_arrow = indirectly_readable + && (requires(const _It& __it) { __it.operator->(); } + || is_reference_v> + || constructible_from, iter_reference_t<_It>>); + + template + concept __common_iter_use_postfix_proxy + = (!requires (_It& __i) { { *__i++ } -> __can_reference; }) + && constructible_from, iter_reference_t<_It>> + && move_constructible>; + } // namespace __detail + + /// An iterator/sentinel adaptor for representing a non-common range. + template _Sent> + requires (!same_as<_It, _Sent>) && copyable<_It> + class common_iterator + { + template + static constexpr bool + _S_noexcept1() + { + if constexpr (is_trivially_default_constructible_v<_Tp>) + return is_nothrow_assignable_v<_Tp&, _Up>; + else + return is_nothrow_constructible_v<_Tp, _Up>; + } + + template + static constexpr bool + _S_noexcept() + { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } + + class __arrow_proxy + { + iter_value_t<_It> _M_keep; + + constexpr + __arrow_proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::move(__x)) { } + + friend class common_iterator; + + public: + constexpr const iter_value_t<_It>* + operator->() const noexcept + { return std::__addressof(_M_keep); } + }; + + class __postfix_proxy + { + iter_value_t<_It> _M_keep; + + constexpr + __postfix_proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::forward>(__x)) { } + + friend class common_iterator; + + public: + constexpr const iter_value_t<_It>& + operator*() const noexcept + { return _M_keep; } + }; + + public: + constexpr + common_iterator() + noexcept(is_nothrow_default_constructible_v<_It>) + requires default_initializable<_It> + : _M_it(), _M_index(0) + { } + + constexpr + common_iterator(_It __i) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_it(std::move(__i)), _M_index(0) + { } + + constexpr + common_iterator(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_sent(std::move(__s)), _M_index(1) + { } + + template + requires convertible_to + && convertible_to + constexpr + common_iterator(const common_iterator<_It2, _Sent2>& __x) + noexcept(_S_noexcept()) + : _M_valueless(), _M_index(__x._M_index) + { + __glibcxx_assert(__x._M_has_value()); + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + std::construct_at(std::__addressof(_M_it), __x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + std::construct_at(std::__addressof(_M_sent), __x._M_sent); + } + } + + common_iterator(const common_iterator&) = default; + + constexpr + common_iterator(const common_iterator& __x) + noexcept(_S_noexcept()) + requires (!is_trivially_copyable_v<_It> || !is_trivially_copyable_v<_Sent>) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = __x._M_it; + else + std::construct_at(std::__addressof(_M_it), __x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = __x._M_sent; + else + std::construct_at(std::__addressof(_M_sent), __x._M_sent); + } + } + + common_iterator(common_iterator&&) = default; + + constexpr + common_iterator(common_iterator&& __x) + noexcept(_S_noexcept<_It, _Sent>()) + requires (!is_trivially_copyable_v<_It> || !is_trivially_copyable_v<_Sent>) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + std::construct_at(std::__addressof(_M_it), std::move(__x._M_it)); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + std::construct_at(std::__addressof(_M_sent), + std::move(__x._M_sent)); + } + } + + constexpr common_iterator& + operator=(const common_iterator&) = default; + + constexpr common_iterator& + operator=(const common_iterator& __x) + noexcept(is_nothrow_copy_assignable_v<_It> + && is_nothrow_copy_assignable_v<_Sent> + && is_nothrow_copy_constructible_v<_It> + && is_nothrow_copy_constructible_v<_Sent>) + requires (!is_trivially_copy_assignable_v<_It> + || !is_trivially_copy_assignable_v<_Sent>) + { + _M_assign(__x); + return *this; + } + + constexpr common_iterator& + operator=(common_iterator&&) = default; + + constexpr common_iterator& + operator=(common_iterator&& __x) + noexcept(is_nothrow_move_assignable_v<_It> + && is_nothrow_move_assignable_v<_Sent> + && is_nothrow_move_constructible_v<_It> + && is_nothrow_move_constructible_v<_Sent>) + requires (!is_trivially_move_assignable_v<_It> + || !is_trivially_move_assignable_v<_Sent>) + { + _M_assign(std::move(__x)); + return *this; + } + + template + requires convertible_to + && convertible_to + && assignable_from<_It&, const _It2&> + && assignable_from<_Sent&, const _Sent2&> + constexpr common_iterator& + operator=(const common_iterator<_It2, _Sent2>& __x) + noexcept(is_nothrow_constructible_v<_It, const _It2&> + && is_nothrow_constructible_v<_Sent, const _Sent2&> + && is_nothrow_assignable_v<_It&, const _It2&> + && is_nothrow_assignable_v<_Sent&, const _Sent2&>) + { + __glibcxx_assert(__x._M_has_value()); + _M_assign(__x); + return *this; + } + +#if __cpp_concepts >= 202002L // Constrained special member functions + ~common_iterator() = default; + + constexpr + ~common_iterator() + requires (!is_trivially_destructible_v<_It> + || !is_trivially_destructible_v<_Sent>) +#else + constexpr + ~common_iterator() +#endif + { + if (_M_index == 0) + _M_it.~_It(); + else if (_M_index == 1) + _M_sent.~_Sent(); + } + + [[nodiscard]] + constexpr decltype(auto) + operator*() + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + [[nodiscard]] + constexpr decltype(auto) + operator*() const requires __detail::__dereferenceable + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + [[nodiscard]] + constexpr auto + operator->() const requires __detail::__common_iter_has_arrow<_It> + { + __glibcxx_assert(_M_index == 0); + if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); }) + return _M_it; + else if constexpr (is_reference_v>) + { + auto&& __tmp = *_M_it; + return std::__addressof(__tmp); + } + else + return __arrow_proxy{*_M_it}; + } + + constexpr common_iterator& + operator++() + { + __glibcxx_assert(_M_index == 0); + ++_M_it; + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_index == 0); + if constexpr (forward_iterator<_It>) + { + common_iterator __tmp = *this; + ++*this; + return __tmp; + } + else if constexpr (!__detail::__common_iter_use_postfix_proxy<_It>) + return _M_it++; + else + { + __postfix_proxy __p(**this); + ++*this; + return __p; + } + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> + friend constexpr bool + operator== [[nodiscard]] (const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0000: + case 0b0101: + return true; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2> + friend constexpr bool + operator== [[nodiscard]] (const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return true; + case 0b0000: + return __x._M_it == __y._M_it; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _It2, sized_sentinel_for<_It> _Sent2> + requires sized_sentinel_for<_Sent, _It2> + friend constexpr iter_difference_t<_It2> + operator- [[nodiscard]] (const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return 0; + case 0b0000: + return __x._M_it - __y._M_it; + case 0b0001: + return __x._M_it - __y._M_sent; + case 0b0100: + return __x._M_sent - __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + [[nodiscard]] + friend constexpr iter_rvalue_reference_t<_It> + iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(std::declval()))) + requires input_iterator<_It> + { + __glibcxx_assert(__i._M_index == 0); + return ranges::iter_move(__i._M_it); + } + + template _It2, typename _Sent2> + friend constexpr void + iter_swap(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + noexcept(noexcept(ranges::iter_swap(std::declval(), + std::declval()))) + { + __glibcxx_assert(__x._M_index == 0); + __glibcxx_assert(__y._M_index == 0); + return ranges::iter_swap(__x._M_it, __y._M_it); + } + + private: + template _Sent2> + requires (!same_as<_It2, _Sent2>) && copyable<_It2> + friend class common_iterator; + + constexpr bool + _M_has_value() const noexcept { return _M_index != _S_valueless; } + + template + constexpr void + _M_assign(_CIt&& __x) + { + if (_M_index == __x._M_index) + { + if (_M_index == 0) + _M_it = std::forward<_CIt>(__x)._M_it; + else if (_M_index == 1) + _M_sent = std::forward<_CIt>(__x)._M_sent; + } + else + { + if (_M_index == 0) + _M_it.~_It(); + else if (_M_index == 1) + _M_sent.~_Sent(); + _M_index = _S_valueless; + + if (__x._M_index == 0) + std::construct_at(std::__addressof(_M_it), + std::forward<_CIt>(__x)._M_it); + else if (__x._M_index == 1) + std::construct_at(std::__addressof(_M_sent), + std::forward<_CIt>(__x)._M_sent); + _M_index = __x._M_index; + } + } + + union + { + _It _M_it; + _Sent _M_sent; + unsigned char _M_valueless; + }; + unsigned char _M_index; // 0 == _M_it, 1 == _M_sent, 2 == valueless + + static constexpr unsigned char _S_valueless{2}; + }; + + template + struct incrementable_traits> + { + using difference_type = iter_difference_t<_It>; + }; + + template + struct iterator_traits> + { + private: + template + struct __ptr + { + using type = void; + }; + + template + requires __detail::__common_iter_has_arrow<_Iter> + struct __ptr<_Iter> + { + using _CIter = common_iterator<_Iter, _Sent>; + using type = decltype(std::declval().operator->()); + }; + + static auto + _S_iter_cat() + { + if constexpr (requires { requires derived_from<__iter_category_t<_It>, + forward_iterator_tag>; }) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + public: + using iterator_concept = __conditional_t, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = decltype(_S_iter_cat()); + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + using pointer = typename __ptr<_It>::type; + using reference = iter_reference_t<_It>; + }; + + // [iterators.counted] Counted iterators + + namespace __detail + { + template + struct __counted_iter_value_type + { }; + + template + struct __counted_iter_value_type<_It> + { using value_type = iter_value_t<_It>; }; + + template + struct __counted_iter_concept + { }; + + template + requires requires { typename _It::iterator_concept; } + struct __counted_iter_concept<_It> + { using iterator_concept = typename _It::iterator_concept; }; + + template + struct __counted_iter_cat + { }; + + template + requires requires { typename _It::iterator_category; } + struct __counted_iter_cat<_It> + { using iterator_category = typename _It::iterator_category; }; + } + + /// An iterator adaptor that keeps track of the distance to the end. + template + class counted_iterator + : public __detail::__counted_iter_value_type<_It>, + public __detail::__counted_iter_concept<_It>, + public __detail::__counted_iter_cat<_It> + { + public: + using iterator_type = _It; + // value_type defined in __counted_iter_value_type + using difference_type = iter_difference_t<_It>; + // iterator_concept defined in __counted_iter_concept + // iterator_category defined in __counted_iter_cat + + constexpr counted_iterator() requires default_initializable<_It> = default; + + constexpr + counted_iterator(_It __i, iter_difference_t<_It> __n) + : _M_current(std::move(__i)), _M_length(__n) + { __glibcxx_assert(__n >= 0); } + + template + requires convertible_to + constexpr + counted_iterator(const counted_iterator<_It2>& __x) + : _M_current(__x._M_current), _M_length(__x._M_length) + { } + + template + requires assignable_from<_It&, const _It2&> + constexpr counted_iterator& + operator=(const counted_iterator<_It2>& __x) + { + _M_current = __x._M_current; + _M_length = __x._M_length; + return *this; + } + + [[nodiscard]] + constexpr const _It& + base() const & noexcept + { return _M_current; } + + [[nodiscard]] + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + [[nodiscard]] + constexpr iter_difference_t<_It> + count() const noexcept { return _M_length; } + + [[nodiscard]] + constexpr decltype(auto) + operator*() + noexcept(noexcept(*_M_current)) + { + __glibcxx_assert( _M_length > 0 ); + return *_M_current; + } + + [[nodiscard]] + constexpr decltype(auto) + operator*() const + noexcept(noexcept(*_M_current)) + requires __detail::__dereferenceable + { + __glibcxx_assert( _M_length > 0 ); + return *_M_current; + } + + [[nodiscard]] + constexpr auto + operator->() const noexcept + requires contiguous_iterator<_It> + { return std::to_address(_M_current); } + + constexpr counted_iterator& + operator++() + { + __glibcxx_assert(_M_length > 0); + ++_M_current; + --_M_length; + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_length > 0); + --_M_length; + __try + { + return _M_current++; + } __catch(...) { + ++_M_length; + __throw_exception_again; + } + } + + constexpr counted_iterator + operator++(int) requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr counted_iterator& + operator--() requires bidirectional_iterator<_It> + { + --_M_current; + ++_M_length; + return *this; + } + + constexpr counted_iterator + operator--(int) requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + [[nodiscard]] + constexpr counted_iterator + operator+(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current + __n, _M_length - __n); } + + [[nodiscard]] + friend constexpr counted_iterator + operator+(iter_difference_t<_It> __n, const counted_iterator& __x) + requires random_access_iterator<_It> + { return __x + __n; } + + constexpr counted_iterator& + operator+=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n <= _M_length); + _M_current += __n; + _M_length -= __n; + return *this; + } + + [[nodiscard]] + constexpr counted_iterator + operator-(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current - __n, _M_length + __n); } + + template _It2> + [[nodiscard]] + friend constexpr iter_difference_t<_It2> + operator-(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length - __x._M_length; } + + [[nodiscard]] + friend constexpr iter_difference_t<_It> + operator-(const counted_iterator& __x, default_sentinel_t) + { return -__x._M_length; } + + [[nodiscard]] + friend constexpr iter_difference_t<_It> + operator-(default_sentinel_t, const counted_iterator& __y) + { return __y._M_length; } + + constexpr counted_iterator& + operator-=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(-__n <= _M_length); + _M_current -= __n; + _M_length += __n; + return *this; + } + + [[nodiscard]] + constexpr decltype(auto) + operator[](iter_difference_t<_It> __n) const + noexcept(noexcept(_M_current[__n])) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n < _M_length); + return _M_current[__n]; + } + + template _It2> + [[nodiscard]] + friend constexpr bool + operator==(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __x._M_length == __y._M_length; } + + [[nodiscard]] + friend constexpr bool + operator==(const counted_iterator& __x, default_sentinel_t) + { return __x._M_length == 0; } + + template _It2> + [[nodiscard]] + friend constexpr strong_ordering + operator<=>(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length <=> __x._M_length; } + + [[nodiscard]] + friend constexpr iter_rvalue_reference_t<_It> + iter_move(const counted_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + requires input_iterator<_It> + { + __glibcxx_assert( __i._M_length > 0 ); + return ranges::iter_move(__i._M_current); + } + + template _It2> + friend constexpr void + iter_swap(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { + __glibcxx_assert( __x._M_length > 0 && __y._M_length > 0 ); + ranges::iter_swap(__x._M_current, __y._M_current); + } + + private: + template friend class counted_iterator; + + _It _M_current = _It(); + iter_difference_t<_It> _M_length = 0; + }; + + template + requires same_as<__detail::__iter_traits<_It>, iterator_traits<_It>> + struct iterator_traits> : iterator_traits<_It> + { + using pointer = __conditional_t, + add_pointer_t>, + void>; + }; + +#if __cplusplus > 202020L + template + using iter_const_reference_t + = common_reference_t&&, iter_reference_t<_It>>; + + template class basic_const_iterator; + + namespace __detail + { + template + concept __constant_iterator = input_iterator<_It> + && same_as, iter_reference_t<_It>>; + + template + inline constexpr bool __is_const_iterator = false; + + template + inline constexpr bool __is_const_iterator> = true; + + template + concept __not_a_const_iterator = !__is_const_iterator<_Tp>; + + template + using __iter_const_rvalue_reference_t + = common_reference_t&&, iter_rvalue_reference_t<_It>>; + + template + struct __basic_const_iterator_iter_cat + { }; + + template + struct __basic_const_iterator_iter_cat<_It> + { using iterator_category = __iter_category_t<_It>; }; + } // namespace detail + + template + using const_iterator + = __conditional_t<__detail::__constant_iterator<_It>, _It, basic_const_iterator<_It>>; + + namespace __detail + { + template + struct __const_sentinel + { using type = _Sent; }; + + template + struct __const_sentinel<_Sent> + { using type = const_iterator<_Sent>; }; + } // namespace __detail + + template + using const_sentinel = typename __detail::__const_sentinel<_Sent>::type; + + template + class basic_const_iterator + : public __detail::__basic_const_iterator_iter_cat<_It> + { + _It _M_current = _It(); + using __reference = iter_const_reference_t<_It>; + using __rvalue_reference = __detail::__iter_const_rvalue_reference_t<_It>; + + static auto + _S_iter_concept() + { + if constexpr (contiguous_iterator<_It>) + return contiguous_iterator_tag{}; + else if constexpr (random_access_iterator<_It>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_iterator<_It>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_iterator<_It>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + template friend class basic_const_iterator; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + + basic_const_iterator() requires default_initializable<_It> = default; + + constexpr + basic_const_iterator(_It __current) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_current(std::move(__current)) + { } + + template _It2> + constexpr + basic_const_iterator(basic_const_iterator<_It2> __current) + noexcept(is_nothrow_constructible_v<_It, _It2>) + : _M_current(std::move(__current._M_current)) + { } + + template<__detail::__different_from _Tp> + requires convertible_to<_Tp, _It> + constexpr + basic_const_iterator(_Tp&& __current) + noexcept(is_nothrow_constructible_v<_It, _Tp>) + : _M_current(std::forward<_Tp>(__current)) + { } + + constexpr const _It& + base() const & noexcept + { return _M_current; } + + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + constexpr __reference + operator*() const + noexcept(noexcept(static_cast<__reference>(*_M_current))) + { return static_cast<__reference>(*_M_current); } + + constexpr const auto* + operator->() const + noexcept(contiguous_iterator<_It> || noexcept(*_M_current)) + requires is_lvalue_reference_v> + && same_as>, value_type> + { + if constexpr (contiguous_iterator<_It>) + return std::to_address(_M_current); + else + return std::__addressof(*_M_current); + } + + constexpr basic_const_iterator& + operator++() + noexcept(noexcept(++_M_current)) + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + noexcept(noexcept(++_M_current)) + { ++_M_current; } + + constexpr basic_const_iterator + operator++(int) + noexcept(noexcept(++*this) && is_nothrow_copy_constructible_v) + requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr basic_const_iterator& + operator--() + noexcept(noexcept(--_M_current)) + requires bidirectional_iterator<_It> + { + --_M_current; + return *this; + } + + constexpr basic_const_iterator + operator--(int) + noexcept(noexcept(--*this) && is_nothrow_copy_constructible_v) + requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr basic_const_iterator& + operator+=(difference_type __n) + noexcept(noexcept(_M_current += __n)) + requires random_access_iterator<_It> + { + _M_current += __n; + return *this; + } + + constexpr basic_const_iterator& + operator-=(difference_type __n) + noexcept(noexcept(_M_current -= __n)) + requires random_access_iterator<_It> + { + _M_current -= __n; + return *this; + } + + constexpr __reference + operator[](difference_type __n) const + noexcept(noexcept(static_cast<__reference>(_M_current[__n]))) + requires random_access_iterator<_It> + { return static_cast<__reference>(_M_current[__n]); } + + template _Sent> + constexpr bool + operator==(const _Sent& __s) const + noexcept(noexcept(_M_current == __s)) + { return _M_current == __s; } + + template<__detail::__not_a_const_iterator _CIt> + requires __detail::__constant_iterator<_CIt> && convertible_to<_It, _CIt> + constexpr + operator _CIt() const& + { return _M_current; } + + template<__detail::__not_a_const_iterator _CIt> + requires __detail::__constant_iterator<_CIt> && convertible_to<_It, _CIt> + constexpr + operator _CIt() && + { return std::move(_M_current); } + + constexpr bool + operator<(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current < __y._M_current)) + requires random_access_iterator<_It> + { return _M_current < __y._M_current; } + + constexpr bool + operator>(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current > __y._M_current)) + requires random_access_iterator<_It> + { return _M_current > __y._M_current; } + + constexpr bool + operator<=(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current <= __y._M_current)) + requires random_access_iterator<_It> + { return _M_current <= __y._M_current; } + + constexpr bool + operator>=(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current >= __y._M_current)) + requires random_access_iterator<_It> + { return _M_current >= __y._M_current; } + + constexpr auto + operator<=>(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current <=> __y._M_current)) + requires random_access_iterator<_It> && three_way_comparable<_It> + { return _M_current <=> __y._M_current; } + + template<__detail::__different_from _It2> + constexpr bool + operator<(const _It2& __y) const + noexcept(noexcept(_M_current < __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current < __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator>(const _It2& __y) const + noexcept(noexcept(_M_current > __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current > __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator<=(const _It2& __y) const + noexcept(noexcept(_M_current <= __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current <= __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator>=(const _It2& __y) const + noexcept(noexcept(_M_current >= __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current >= __y; } + + template<__detail::__different_from _It2> + constexpr auto + operator<=>(const _It2& __y) const + noexcept(noexcept(_M_current <=> __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + && three_way_comparable_with<_It, _It2> + { return _M_current <=> __y; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator<(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x < __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x < __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator>(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x > __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x > __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator<=(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x <= __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x <= __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator>=(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x >= __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x >= __y._M_current; } + + friend constexpr basic_const_iterator + operator+(const basic_const_iterator& __i, difference_type __n) + noexcept(noexcept(basic_const_iterator(__i._M_current + __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current + __n); } + + friend constexpr basic_const_iterator + operator+(difference_type __n, const basic_const_iterator& __i) + noexcept(noexcept(basic_const_iterator(__i._M_current + __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current + __n); } + + friend constexpr basic_const_iterator + operator-(const basic_const_iterator& __i, difference_type __n) + noexcept(noexcept(basic_const_iterator(__i._M_current - __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current - __n); } + + template _Sent> + constexpr difference_type + operator-(const _Sent& __y) const + noexcept(noexcept(_M_current - __y)) + { return _M_current - __y; } + + template<__detail::__not_a_const_iterator _Sent> + requires sized_sentinel_for<_Sent, _It> + friend constexpr difference_type + operator-(const _Sent& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x - __y._M_current)) + { return __x - __y._M_current; } + + friend constexpr __rvalue_reference + iter_move(const basic_const_iterator& __i) + noexcept(noexcept(static_cast<__rvalue_reference>(ranges::iter_move(__i._M_current)))) + { return static_cast<__rvalue_reference>(ranges::iter_move(__i._M_current)); } + }; + + template _Up> + requires input_iterator> + struct common_type, _Up> + { using type = basic_const_iterator>; }; + + template _Up> + requires input_iterator> + struct common_type<_Up, basic_const_iterator<_Tp>> + { using type = basic_const_iterator>; }; + + template _Up> + requires input_iterator> + struct common_type, basic_const_iterator<_Up>> + { using type = basic_const_iterator>; }; + + template + constexpr const_iterator<_It> + make_const_iterator(_It __it) + noexcept(is_nothrow_convertible_v<_It, const_iterator<_It>>) + { return __it; } + + template + constexpr const_sentinel<_Sent> + make_const_sentinel(_Sent __s) + noexcept(is_nothrow_convertible_v<_Sent, const_sentinel<_Sent>>) + { return __s; } +#endif // C++23 +#endif // C++20 + + /// @} group iterators + + template + _GLIBCXX20_CONSTEXPR + auto + __niter_base(move_iterator<_Iterator> __it) + -> decltype(make_move_iterator(__niter_base(__it.base()))) + { return make_move_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template + _GLIBCXX20_CONSTEXPR + auto + __miter_base(move_iterator<_Iterator> __it) + -> decltype(__miter_base(__it.base())) + { return __miter_base(__it.base()); } + +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \ + std::__make_move_if_noexcept_iterator(_Iter) +#else +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) +#endif // C++11 + +#if __cpp_deduction_guides >= 201606 + // These helper traits are used for deduction guides + // of associative containers. + template + using __iter_key_t = remove_const_t< +#if __glibcxx_tuple_like // >= C++23 + tuple_element_t<0, typename iterator_traits<_InputIterator>::value_type>>; +#else + typename iterator_traits<_InputIterator>::value_type::first_type>; +#endif + + template + using __iter_val_t +#if __glibcxx_tuple_like // >= C++23 + = tuple_element_t<1, typename iterator_traits<_InputIterator>::value_type>; +#else + = typename iterator_traits<_InputIterator>::value_type::second_type; +#endif + + template + struct pair; + + template + using __iter_to_alloc_t + = pair, __iter_val_t<_InputIterator>>; +#endif // __cpp_deduction_guides + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#endif diff --git a/template/sysroot/include/bits/stl_iterator_base_funcs.h b/template/sysroot/include/bits/stl_iterator_base_funcs.h new file mode 100644 index 0000000..2c9eaf9 --- /dev/null +++ b/template/sysroot/include/bits/stl_iterator_base_funcs.h @@ -0,0 +1,259 @@ +// Functions used by iterators -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_funcs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility + * functions, such as distance() and advance(). + */ + +#ifndef _STL_ITERATOR_BASE_FUNCS_H +#define _STL_ITERATOR_BASE_FUNCS_H 1 + +#pragma GCC system_header + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + // Forward declaration for the overloads of __distance. + template struct _List_iterator; + template struct _List_const_iterator; +_GLIBCXX_END_NAMESPACE_CONTAINER + + template + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + + template + __attribute__((__always_inline__)) + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + return __last - __first; + } + +#if _GLIBCXX_USE_CXX11_ABI + // Forward declaration because of the qualified call in distance. + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>, + _GLIBCXX_STD_C::_List_iterator<_Tp>, + input_iterator_tag); + + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>, + _GLIBCXX_STD_C::_List_const_iterator<_Tp>, + input_iterator_tag); +#endif + +#if __cplusplus >= 201103L + // Give better error if std::distance called with a non-Cpp17InputIterator. + template + void + __distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete; +#endif + + /** + * @brief A generalization of pointer arithmetic. + * @param __first An input iterator. + * @param __last An input iterator. + * @return The distance between them. + * + * Returns @c n such that __first + n == __last. This requires + * that @p __last must be reachable from @p __first. Note that @c + * n may be negative. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + inline _GLIBCXX17_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + // concept requirements -- taken care of in __distance + return std::__distance(__first, __last, + std::__iterator_category(__first)); + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_assert(__n >= 0); + while (__n--) + ++__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + if (__n > 0) + while (__n--) + ++__i; + else + while (__n++) + --__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + if (__builtin_constant_p(__n) && __n == 1) + ++__i; + else if (__builtin_constant_p(__n) && __n == -1) + --__i; + else + __i += __n; + } + +#if __cplusplus >= 201103L + // Give better error if std::advance called with a non-Cpp17InputIterator. + template + void + __advance(_OutputIterator&, _Distance, output_iterator_tag) = delete; +#endif + + /** + * @brief A generalization of pointer arithmetic. + * @param __i An input iterator. + * @param __n The @a delta by which to change @p __i. + * @return Nothing. + * + * This increments @p i by @p n. For bidirectional and random access + * iterators, @p __n may be negative, in which case @p __i is decremented. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + __attribute__((__always_inline__)) + inline _GLIBCXX17_CONSTEXPR void + advance(_InputIterator& __i, _Distance __n) + { + // concept requirements -- taken care of in __advance + typename iterator_traits<_InputIterator>::difference_type __d = __n; + std::__advance(__i, __d, std::__iterator_category(__i)); + } + +#if __cplusplus >= 201103L + + template + _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR _InputIterator + next(_InputIterator __x, typename + iterator_traits<_InputIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + std::advance(__x, __n); + return __x; + } + + template + _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]] + inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator + prev(_BidirectionalIterator __x, typename + iterator_traits<_BidirectionalIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + std::advance(__x, -__n); + return __x; + } + +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_FUNCS_H */ diff --git a/template/sysroot/include/bits/stl_iterator_base_types.h b/template/sysroot/include/bits/stl_iterator_base_types.h new file mode 100644 index 0000000..07beec3 --- /dev/null +++ b/template/sysroot/include/bits/stl_iterator_base_types.h @@ -0,0 +1,272 @@ +// Types used in iterator implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_types.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility types, + * such as iterator_traits and struct iterator. + */ + +#ifndef _STL_ITERATOR_BASE_TYPES_H +#define _STL_ITERATOR_BASE_TYPES_H 1 + +#pragma GCC system_header + +#include + +#if __cplusplus >= 201103L +# include // For __void_t, is_convertible +#endif + +#if __cplusplus > 201703L && __cpp_concepts >= 201907L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup iterators Iterators + * Abstractions for uniform iterating through various underlying types. + */ + ///@{ + + /** + * @defgroup iterator_tags Iterator Tags + * These are empty types, used to distinguish different iterators. The + * distinction is not made by what they contain, but simply by what they + * are. Different underlying algorithms can then be used based on the + * different operations supported by different iterator types. + */ + ///@{ + /// Marking input iterators. + struct input_iterator_tag { }; + + /// Marking output iterators. + struct output_iterator_tag { }; + + /// Forward iterators support a superset of input iterator operations. + struct forward_iterator_tag : public input_iterator_tag { }; + + /// Bidirectional iterators support a superset of forward iterator + /// operations. + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + + /// Random-access iterators support a superset of bidirectional + /// iterator operations. + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + +#if __cplusplus > 201703L + /// Contiguous iterators point to objects stored contiguously in memory. + struct contiguous_iterator_tag : public random_access_iterator_tag { }; +#endif + ///@} + + /** + * @brief Common %iterator class. + * + * This class does nothing but define nested typedefs. %Iterator classes + * can inherit from this class to save some work. The typedefs are then + * used in specializations and overloading. + * + * In particular, there are no default implementations of requirements + * such as @c operator++ and the like. (How could there be?) + */ + template + struct _GLIBCXX17_DEPRECATED iterator + { + /// One of the @link iterator_tags tag types@endlink. + typedef _Category iterator_category; + /// The type "pointed to" by the iterator. + typedef _Tp value_type; + /// Distance between iterators is represented as this type. + typedef _Distance difference_type; + /// This type represents a pointer-to-value_type. + typedef _Pointer pointer; + /// This type represents a reference-to-value_type. + typedef _Reference reference; + }; + + /** + * @brief Traits class for iterators. + * + * This class does nothing but define nested typedefs. The general + * version simply @a forwards the nested typedefs from the Iterator + * argument. Specialized versions for pointers and pointers-to-const + * provide tighter, more correct semantics. + */ + template + struct iterator_traits; + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 + template> + struct __iterator_traits { }; + +#if ! __cpp_lib_concepts + + template + struct __iterator_traits<_Iterator, + __void_t> + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // ! concepts + + template + struct iterator_traits + : public __iterator_traits<_Iterator> { }; + +#else // ! C++11 + template + struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // C++11 + +#if __cplusplus > 201703L + /// Partial specialization for object pointer types. + template +#if __cpp_concepts >= 201907L + requires is_object_v<_Tp> +#endif + struct iterator_traits<_Tp*> + { + using iterator_concept = contiguous_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = remove_cv_t<_Tp>; + using difference_type = ptrdiff_t; + using pointer = _Tp*; + using reference = _Tp&; + }; +#else + /// Partial specialization for pointer types. + template + struct iterator_traits<_Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + + /// Partial specialization for const pointer types. + template + struct iterator_traits + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; +#endif + + /** + * This function is not a part of the C++ standard but is syntactic + * sugar for internal library use only. + */ + template + __attribute__((__always_inline__)) + inline _GLIBCXX_CONSTEXPR + typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } + + ///@} + +#if __cplusplus >= 201103L + template + using __iter_category_t + = typename iterator_traits<_Iter>::iterator_category; + + template + using _RequireInputIter = + __enable_if_t, + input_iterator_tag>::value>; + + template> + struct __is_random_access_iter + : is_base_of + { + typedef is_base_of _Base; + enum { __value = _Base::value }; + }; +#else + template, + typename _Cat = typename _Traits::iterator_category> + struct __is_random_access_iter + { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_TYPES_H */ diff --git a/template/sysroot/include/bits/stl_numeric.h b/template/sysroot/include/bits/stl_numeric.h new file mode 100644 index 0000000..fe91115 --- /dev/null +++ b/template/sysroot/include/bits/stl_numeric.h @@ -0,0 +1,411 @@ +// Numeric functions implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_numeric.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{numeric} + */ + +#ifndef _STL_NUMERIC_H +#define _STL_NUMERIC_H 1 + +#include +#include +#include // For _GLIBCXX_MOVE + + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup numeric_ops Generalized Numeric operations + * @ingroup algorithms + */ + +#if __cplusplus >= 201103L + /** + * @brief Create a range of sequentially increasing values. + * + * For each element in the range @p [first,last) assigns @p value and + * increments @p value as if by @p ++value. + * + * @param __first Start of range. + * @param __last End of range. + * @param __value Starting value. + * @return Nothing. + * @ingroup numeric_ops + */ + template + _GLIBCXX20_CONSTEXPR + void + iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + { + *__first = __value; + ++__value; + } + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + +#if __cplusplus > 201703L +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// DR 2055. std::move in std::accumulate and other algorithms +# define _GLIBCXX_MOVE_IF_20(_E) std::move(_E) +#else +# define _GLIBCXX_MOVE_IF_20(_E) _E +#endif + + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Accumulate values in a range. + * + * Accumulates the values in the range [first,last) using operator+(). The + * initial value is @a init. The values are processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = _GLIBCXX_MOVE_IF_20(__init) + *__first; + return __init; + } + + /** + * @brief Accumulate values in a range with operation. + * + * Accumulates the values in the range `[first,last)` using the function + * object `__binary_op`. The initial value is `__init`. The values are + * processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op Function object to accumulate with. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, multiplies successive + * elements from the two ranges and adds each product into the accumulated + * value using operator+(). The values in the ranges are processed in + * order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = _GLIBCXX_MOVE_IF_20(__init) + (*__first1 * *__first2); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, applies @p __binary_op2 to + * successive elements from the two ranges and accumulates each result into + * the accumulated value using @p __binary_op1. The values in the ranges are + * processed in order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @param __binary_op1 Function object to accumulate with. + * @param __binary_op2 Function object to apply to pairs of input values. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = __binary_op1(_GLIBCXX_MOVE_IF_20(__init), + __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using the @c + operator. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = _GLIBCXX_MOVE_IF_20(__value) + *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using @p __binary_op. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = __binary_op(_GLIBCXX_MOVE_IF_20(__value), *__first); + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [first,last) using operator-() and writes the result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sums. + * @return Iterator pointing just beyond the values written to result. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 539. partial_sum and adjacent_difference should mention requirements + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, + _InputIterator __last, _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __tmp - _GLIBCXX_MOVE_IF_20(__value); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [__first,__last) using the function object @p __binary_op and writes the + * result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to result. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 539. partial_sum and adjacent_difference should mention requirements + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __binary_op(__tmp, _GLIBCXX_MOVE_IF_20(__value)); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + /// @} group numeric_ops + +#undef _GLIBCXX_MOVE_IF_20 + +_GLIBCXX_END_NAMESPACE_ALGO +} // namespace std + +#endif /* _STL_NUMERIC_H */ diff --git a/template/sysroot/include/bits/stl_pair.h b/template/sysroot/include/bits/stl_pair.h new file mode 100644 index 0000000..4531741 --- /dev/null +++ b/template/sysroot/include/bits/stl_pair.h @@ -0,0 +1,1335 @@ +// Pair implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_pair.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _STL_PAIR_H +#define _STL_PAIR_H 1 + +#if __cplusplus >= 201103L +# include // for std::__decay_and_strip +# include // for std::move / std::forward, and std::swap +# include // for std::tuple_element, std::tuple_size +#endif +#if __cplusplus >= 202002L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#if __cplusplus >= 201103L + /// Tag type for piecewise construction of std::pair objects. + struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; + + /// Tag for piecewise construction of std::pair objects. + _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = + piecewise_construct_t(); + + /// @cond undocumented + + // Forward declarations. + template + struct pair; + + template + class tuple; + + // Declarations of std::array and its std::get overloads, so that + // std::tuple_cat can use them if is included before . + // We also declare the other std::get overloads here so that they're + // visible to the P2165R4 tuple-like constructors of pair and tuple. + template + struct array; + + template + struct _Index_tuple; + + template + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(pair<_Tp1, _Tp2>& __in) noexcept; + + template + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(pair<_Tp1, _Tp2>&& __in) noexcept; + + template + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(const pair<_Tp1, _Tp2>& __in) noexcept; + + template + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(const pair<_Tp1, _Tp2>&& __in) noexcept; + + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>& + get(tuple<_Elements...>& __t) noexcept; + + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>& + get(const tuple<_Elements...>& __t) noexcept; + + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>&& + get(tuple<_Elements...>&& __t) noexcept; + + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& + get(const tuple<_Elements...>&& __t) noexcept; + + template + constexpr _Tp& + get(array<_Tp, _Nm>&) noexcept; + + template + constexpr _Tp&& + get(array<_Tp, _Nm>&&) noexcept; + + template + constexpr const _Tp& + get(const array<_Tp, _Nm>&) noexcept; + + template + constexpr const _Tp&& + get(const array<_Tp, _Nm>&&) noexcept; + +#if ! __cpp_lib_concepts + // Concept utility functions, reused in conditionally-explicit + // constructors. + // See PR 70437, don't look at is_constructible or + // is_convertible if the types are the same to + // avoid querying those properties for incomplete types. + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return __and_, + is_constructible<_T2, const _U2&>>::value; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return __and_, + is_convertible>::value; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return __and_, + is_constructible<_T2, _U2&&>>::value; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return __and_, + is_convertible<_U2&&, _T2>>::value; + } + }; + + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return false; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return false; + } + }; +#endif // lib concepts +#endif // C++11 + +#if __glibcxx_tuple_like // >= C++23 + template + inline constexpr bool __is_tuple_v = false; + + template + inline constexpr bool __is_tuple_v> = true; + + // TODO: Reuse __is_tuple_like from ? + template + inline constexpr bool __is_tuple_like_v = false; + + template + inline constexpr bool __is_tuple_like_v> = true; + + template + inline constexpr bool __is_tuple_like_v> = true; + + template + inline constexpr bool __is_tuple_like_v> = true; + + // __is_tuple_like_v is defined in . + + template + concept __tuple_like = __is_tuple_like_v>; + + template + concept __pair_like = __tuple_like<_Tp> && tuple_size_v> == 2; + + template + concept __eligible_tuple_like + = __detail::__different_from<_Tp, _Tuple> && __tuple_like<_Tp> + && (tuple_size_v> == tuple_size_v<_Tuple>) + && !ranges::__detail::__is_subrange>; + + template + concept __eligible_pair_like + = __detail::__different_from<_Tp, _Pair> && __pair_like<_Tp> + && !ranges::__detail::__is_subrange>; +#endif // C++23 + + template class __pair_base + { +#if __cplusplus >= 201103L && ! __cpp_lib_concepts + template friend struct pair; + __pair_base() = default; + ~__pair_base() = default; + __pair_base(const __pair_base&) = default; + __pair_base& operator=(const __pair_base&) = delete; +#endif // C++11 + }; + + /// @endcond + + /** + * @brief Struct holding two objects of arbitrary type. + * + * @tparam _T1 Type of first object. + * @tparam _T2 Type of second object. + * + * + * + * @headerfile utility + */ + template + struct pair + : public __pair_base<_T1, _T2> + { + typedef _T1 first_type; ///< The type of the `first` member + typedef _T2 second_type; ///< The type of the `second` member + + _T1 first; ///< The first member + _T2 second; ///< The second member + +#if __cplusplus >= 201103L + constexpr pair(const pair&) = default; ///< Copy constructor + constexpr pair(pair&&) = default; ///< Move constructor + + template + _GLIBCXX20_CONSTEXPR + pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); + + /// Swap the first members and then the second members. + _GLIBCXX20_CONSTEXPR void + swap(pair& __p) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { + using std::swap; + swap(first, __p.first); + swap(second, __p.second); + } + +#if __glibcxx_ranges_zip // >= C++23 + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of pairs whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. + constexpr void + swap(const pair& __p) const + noexcept(__and_v<__is_nothrow_swappable, + __is_nothrow_swappable>) + requires is_swappable_v && is_swappable_v + { + using std::swap; + swap(first, __p.first); + swap(second, __p.second); + } +#endif // C++23 + + private: + template + _GLIBCXX20_CONSTEXPR + pair(tuple<_Args1...>&, tuple<_Args2...>&, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); + public: + +#if __cpp_lib_concepts + // C++20 implementation using concepts, explicit(bool), fully constexpr. + + /// Default constructor + constexpr + explicit(__not_<__and_<__is_implicitly_default_constructible<_T1>, + __is_implicitly_default_constructible<_T2>>>()) + pair() + requires is_default_constructible_v<_T1> + && is_default_constructible_v<_T2> + : first(), second() + { } + + private: + + /// @cond undocumented + template + static constexpr bool + _S_constructible() + { + if constexpr (is_constructible_v<_T1, _U1>) + return is_constructible_v<_T2, _U2>; + return false; + } + + template + static constexpr bool + _S_nothrow_constructible() + { + if constexpr (is_nothrow_constructible_v<_T1, _U1>) + return is_nothrow_constructible_v<_T2, _U2>; + return false; + } + + template + static constexpr bool + _S_convertible() + { + if constexpr (is_convertible_v<_U1, _T1>) + return is_convertible_v<_U2, _T2>; + return false; + } + + // True if construction from _U1 and _U2 would create a dangling ref. + template + static constexpr bool + _S_dangles() + { +#if __has_builtin(__reference_constructs_from_temporary) + if constexpr (__reference_constructs_from_temporary(_T1, _U1&&)) + return true; + else + return __reference_constructs_from_temporary(_T2, _U2&&); +#else + return false; +#endif + } + +#if __glibcxx_tuple_like // >= C++23 + template + static constexpr bool + _S_constructible_from_pair_like() + { + return _S_constructible(std::declval<_UPair>())), + decltype(std::get<1>(std::declval<_UPair>()))>(); + } + + template + static constexpr bool + _S_convertible_from_pair_like() + { + return _S_convertible(std::declval<_UPair>())), + decltype(std::get<1>(std::declval<_UPair>()))>(); + } + + template + static constexpr bool + _S_dangles_from_pair_like() + { + return _S_dangles(std::declval<_UPair>())), + decltype(std::get<1>(std::declval<_UPair>()))>(); + } +#endif // C++23 + /// @endcond + + public: + + /// Constructor accepting lvalues of `first_type` and `second_type` + constexpr explicit(!_S_convertible()) + pair(const _T1& __x, const _T2& __y) + noexcept(_S_nothrow_constructible()) + requires (_S_constructible()) + : first(__x), second(__y) + { } + + /// Constructor accepting two values of arbitrary types +#if __cplusplus > 202002L + template +#else + template +#endif + requires (_S_constructible<_U1, _U2>()) && (!_S_dangles<_U1, _U2>()) + constexpr explicit(!_S_convertible<_U1, _U2>()) + pair(_U1&& __x, _U2&& __y) + noexcept(_S_nothrow_constructible<_U1, _U2>()) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) + { } + +#if __cplusplus > 202002L + template +#else + template +#endif + requires (_S_constructible<_U1, _U2>()) && (_S_dangles<_U1, _U2>()) + constexpr explicit(!_S_convertible<_U1, _U2>()) + pair(_U1&&, _U2&&) = delete; + + /// Converting constructor from a const `pair` lvalue + template + requires (_S_constructible()) + && (!_S_dangles<_U1, _U2>()) + constexpr explicit(!_S_convertible()) + pair(const pair<_U1, _U2>& __p) + noexcept(_S_nothrow_constructible()) + : first(__p.first), second(__p.second) + { } + + template + requires (_S_constructible()) + && (_S_dangles()) + constexpr explicit(!_S_convertible()) + pair(const pair<_U1, _U2>&) = delete; + + /// Converting constructor from a non-const `pair` rvalue + template + requires (_S_constructible<_U1, _U2>()) && (!_S_dangles<_U1, _U2>()) + constexpr explicit(!_S_convertible<_U1, _U2>()) + pair(pair<_U1, _U2>&& __p) + noexcept(_S_nothrow_constructible<_U1, _U2>()) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) + { } + + template + requires (_S_constructible<_U1, _U2>()) && (_S_dangles<_U1, _U2>()) + constexpr explicit(!_S_convertible<_U1, _U2>()) + pair(pair<_U1, _U2>&&) = delete; + +#if __glibcxx_ranges_zip // >= C++23 + /// Converting constructor from a non-const `pair` lvalue + template + requires (_S_constructible<_U1&, _U2&>()) && (!_S_dangles<_U1&, _U2&>()) + constexpr explicit(!_S_convertible<_U1&, _U2&>()) + pair(pair<_U1, _U2>& __p) + noexcept(_S_nothrow_constructible<_U1&, _U2&>()) + : first(__p.first), second(__p.second) + { } + + template + requires (_S_constructible<_U1&, _U2&>()) && (_S_dangles<_U1&, _U2&>()) + constexpr explicit(!_S_convertible<_U1&, _U2&>()) + pair(pair<_U1, _U2>&) = delete; + + /// Converting constructor from a const `pair` rvalue + template + requires (_S_constructible()) + && (!_S_dangles()) + constexpr explicit(!_S_convertible()) + pair(const pair<_U1, _U2>&& __p) + noexcept(_S_nothrow_constructible()) + : first(std::forward(__p.first)), + second(std::forward(__p.second)) + { } + + template + requires (_S_constructible()) + && (_S_dangles()) + constexpr explicit(!_S_convertible()) + pair(const pair<_U1, _U2>&&) = delete; +#endif // C++23 + +#if __glibcxx_tuple_like // >= C++23 + template<__eligible_pair_like _UPair> + requires (_S_constructible_from_pair_like<_UPair>()) + && (!_S_dangles_from_pair_like<_UPair>()) + constexpr explicit(!_S_convertible_from_pair_like<_UPair>()) + pair(_UPair&& __p) + : first(std::get<0>(std::forward<_UPair>(__p))), + second(std::get<1>(std::forward<_UPair>(__p))) + { } + + template<__eligible_pair_like _UPair> + requires (_S_constructible_from_pair_like<_UPair>()) + && (_S_dangles_from_pair_like<_UPair>()) + constexpr explicit(!_S_convertible_from_pair_like<_UPair>()) + pair(_UPair&&) = delete; +#endif // C++23 + + private: + /// @cond undocumented + template + static constexpr bool + _S_assignable() + { + if constexpr (is_assignable_v<_T1&, _U1>) + return is_assignable_v<_T2&, _U2>; + return false; + } + + template + static constexpr bool + _S_const_assignable() + { + if constexpr (is_assignable_v) + return is_assignable_v; + return false; + } + + template + static constexpr bool + _S_nothrow_assignable() + { + if constexpr (is_nothrow_assignable_v<_T1&, _U1>) + return is_nothrow_assignable_v<_T2&, _U2>; + return false; + } + +#if __glibcxx_tuple_like // >= C++23 + template + static constexpr bool + _S_assignable_from_tuple_like() + { + return _S_assignable(std::declval<_UPair>())), + decltype(std::get<1>(std::declval<_UPair>()))>(); + } + + template + static constexpr bool + _S_const_assignable_from_tuple_like() + { + return _S_const_assignable(std::declval<_UPair>())), + decltype(std::get<1>(std::declval<_UPair>()))>(); + } +#endif // C++23 + /// @endcond + + public: + + pair& operator=(const pair&) = delete; + + /// Copy assignment operator + constexpr pair& + operator=(const pair& __p) + noexcept(_S_nothrow_assignable()) + requires (_S_assignable()) + { + first = __p.first; + second = __p.second; + return *this; + } + + /// Move assignment operator + constexpr pair& + operator=(pair&& __p) + noexcept(_S_nothrow_assignable<_T1, _T2>()) + requires (_S_assignable<_T1, _T2>()) + { + first = std::forward(__p.first); + second = std::forward(__p.second); + return *this; + } + + /// Converting assignment from a const `pair` lvalue + template + constexpr pair& + operator=(const pair<_U1, _U2>& __p) + noexcept(_S_nothrow_assignable()) + requires (_S_assignable()) + { + first = __p.first; + second = __p.second; + return *this; + } + + /// Converting assignment from a non-const `pair` rvalue + template + constexpr pair& + operator=(pair<_U1, _U2>&& __p) + noexcept(_S_nothrow_assignable<_U1, _U2>()) + requires (_S_assignable<_U1, _U2>()) + { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } + +#if __glibcxx_ranges_zip // >= C++23 + /// Copy assignment operator (const) + constexpr const pair& + operator=(const pair& __p) const + requires (_S_const_assignable()) + { + first = __p.first; + second = __p.second; + return *this; + } + + /// Move assignment operator (const) + constexpr const pair& + operator=(pair&& __p) const + requires (_S_const_assignable()) + { + first = std::forward(__p.first); + second = std::forward(__p.second); + return *this; + } + + /// Converting assignment from a const `pair` lvalue + template + constexpr const pair& + operator=(const pair<_U1, _U2>& __p) const + requires (_S_const_assignable()) + { + first = __p.first; + second = __p.second; + return *this; + } + + /// Converting assignment from a non-const `pair` rvalue + template + constexpr const pair& + operator=(pair<_U1, _U2>&& __p) const + requires (_S_const_assignable<_U1, _U2>()) + { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } +#endif // C++23 + +#if __glibcxx_tuple_like // >= C++23 + template<__eligible_pair_like _UPair> + requires (_S_assignable_from_tuple_like<_UPair>()) + constexpr pair& + operator=(_UPair&& __p) + { + first = std::get<0>(std::forward<_UPair>(__p)); + second = std::get<1>(std::forward<_UPair>(__p)); + return *this; + } + + template<__eligible_pair_like _UPair> + requires (_S_const_assignable_from_tuple_like<_UPair>()) + constexpr const pair& + operator=(_UPair&& __p) const + { + first = std::get<0>(std::forward<_UPair>(__p)); + second = std::get<1>(std::forward<_UPair>(__p)); + return *this; + } +#endif // C++23 + +#else // !__cpp_lib_concepts + // C++11/14/17 implementation using enable_if, partially constexpr. + + /// @cond undocumented + // Error if construction from _U1 and _U2 would create a dangling ref. +#if __has_builtin(__reference_constructs_from_temporary) \ + && defined _GLIBCXX_DEBUG +# define __glibcxx_no_dangling_refs(_U1, _U2) \ + static_assert(!__reference_constructs_from_temporary(_T1, _U1) \ + && !__reference_constructs_from_temporary(_T2, _U2), \ + "std::pair constructor creates a dangling reference") +#else +# define __glibcxx_no_dangling_refs(_U1, _U2) +#endif + /// @endcond + + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ + template , + __is_implicitly_default_constructible<_U2>> + ::value, bool>::type = true> + constexpr pair() + : first(), second() { } + + template , + is_default_constructible<_U2>, + __not_< + __and_<__is_implicitly_default_constructible<_U1>, + __is_implicitly_default_constructible<_U2>>>> + ::value, bool>::type = false> + explicit constexpr pair() + : first(), second() { } + + // Shortcut for constraining the templates that don't take pairs. + /// @cond undocumented + using _PCCP = _PCC; + /// @endcond + + /// Construct from two const lvalues, allowing implicit conversions. + template() + && _PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + + /// Construct from two const lvalues, disallowing implicit conversions. + template() + && !_PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + + // Shortcut for constraining the templates that take pairs. + /// @cond undocumented + template + using _PCCFP = _PCC::value + || !is_same<_T2, _U2>::value, + _T1, _T2>; + /// @endcond + + template::template + _ConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template::template + _ConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + +#if _GLIBCXX_USE_DEPRECATED +#if defined(__DEPRECATED) +# define _GLIBCXX_DEPRECATED_PAIR_CTOR \ + __attribute__ ((__deprecated__ ("use 'nullptr' instead of '0' to " \ + "initialize std::pair of move-only " \ + "type and pointer"))) +#else +# define _GLIBCXX_DEPRECATED_PAIR_CTOR +#endif + + private: + /// @cond undocumented + + // A type which can be constructed from literal zero, but not nullptr + struct __zero_as_null_pointer_constant + { + __zero_as_null_pointer_constant(int __zero_as_null_pointer_constant::*) + { } + template::value>> + __zero_as_null_pointer_constant(_Tp) = delete; + }; + /// @endcond + public: + + // Deprecated extensions to DR 811. + // These allow construction from an rvalue and a literal zero, + // in cases where the standard says the zero should be deduced as int + template>, + is_pointer<_T2>, + is_constructible<_T1, _U1>, + __not_>, + is_convertible<_U1, _T1>>::value, + bool> = true> + _GLIBCXX_DEPRECATED_PAIR_CTOR + constexpr + pair(_U1&& __x, __zero_as_null_pointer_constant, ...) + : first(std::forward<_U1>(__x)), second(nullptr) + { __glibcxx_no_dangling_refs(_U1&&, std::nullptr_t); } + + template>, + is_pointer<_T2>, + is_constructible<_T1, _U1>, + __not_>, + __not_>>::value, + bool> = false> + _GLIBCXX_DEPRECATED_PAIR_CTOR + explicit constexpr + pair(_U1&& __x, __zero_as_null_pointer_constant, ...) + : first(std::forward<_U1>(__x)), second(nullptr) + { __glibcxx_no_dangling_refs(_U1&&, std::nullptr_t); } + + template, + __not_>, + is_constructible<_T2, _U2>, + __not_>, + is_convertible<_U2, _T2>>::value, + bool> = true> + _GLIBCXX_DEPRECATED_PAIR_CTOR + constexpr + pair(__zero_as_null_pointer_constant, _U2&& __y, ...) + : first(nullptr), second(std::forward<_U2>(__y)) + { __glibcxx_no_dangling_refs(std::nullptr_t, _U2&&); } + + template, + __not_>, + is_constructible<_T2, _U2>, + __not_>, + __not_>>::value, + bool> = false> + _GLIBCXX_DEPRECATED_PAIR_CTOR + explicit constexpr + pair(__zero_as_null_pointer_constant, _U2&& __y, ...) + : first(nullptr), second(std::forward<_U2>(__y)) + { __glibcxx_no_dangling_refs(std::nullptr_t, _U2&&); } +#undef _GLIBCXX_DEPRECATED_PAIR_CTOR +#endif + + template() + && _PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template() + && !_PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + + template::template + _MoveConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template::template + _MoveConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + +#undef __glibcxx_no_dangling_refs + + pair& + operator=(__conditional_t<__and_, + is_copy_assignable<_T2>>::value, + const pair&, const __nonesuch&> __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + pair& + operator=(__conditional_t<__and_, + is_move_assignable<_T2>>::value, + pair&&, __nonesuch&&> __p) + noexcept(__and_, + is_nothrow_move_assignable<_T2>>::value) + { + first = std::forward(__p.first); + second = std::forward(__p.second); + return *this; + } + + template + typename enable_if<__and_, + is_assignable<_T2&, const _U2&>>::value, + pair&>::type + operator=(const pair<_U1, _U2>& __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + template + typename enable_if<__and_, + is_assignable<_T2&, _U2&&>>::value, + pair&>::type + operator=(pair<_U1, _U2>&& __p) + { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } +#endif // lib concepts +#else + // C++03 implementation + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 265. std::pair::pair() effects overly restrictive + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ + pair() : first(), second() { } + + /// Two objects may be passed to a `pair` constructor to be copied. + pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + + /// Templated constructor to convert from other pairs. + template + pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) + { +#if __has_builtin(__reference_constructs_from_temporary) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" + typedef int _DanglingCheck1[ + __reference_constructs_from_temporary(_T1, const _U1&) ? -1 : 1 + ]; + typedef int _DanglingCheck2[ + __reference_constructs_from_temporary(_T2, const _U2&) ? -1 : 1 + ]; +#pragma GCC diagnostic pop +#endif + } +#endif // C++11 + }; + + /// @relates pair @{ + +#if __cpp_deduction_guides >= 201606 + template pair(_T1, _T2) -> pair<_T1, _T2>; +#endif + +#if __cpp_lib_three_way_comparison && __cpp_lib_concepts + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3865. Sorting a range of pairs + + /// Two pairs are equal iff their members are equal. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) + { return __x.first == __y.first && __x.second == __y.second; } + + /** Defines a lexicographical order for pairs. + * + * For two pairs of comparable types, `P` is ordered before `Q` if + * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` + * are equivalent (neither is less than the other) and `P.second` is + * less than `Q.second`. + */ + template + constexpr common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>, + __detail::__synth3way_t<_T2, _U2>> + operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) + { + if (auto __c = __detail::__synth3way(__x.first, __y.first); __c != 0) + return __c; + return __detail::__synth3way(__x.second, __y.second); + } +#else + /// Two pairs of the same type are equal iff their members are equal. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first == __y.first && __x.second == __y.second; } + + /** Defines a lexicographical order for pairs. + * + * For two pairs of the same type, `P` is ordered before `Q` if + * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` + * are equivalent (neither is less than the other) and `P.second` is less + * than `Q.second`. + */ + template + inline _GLIBCXX_CONSTEXPR bool + operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first < __y.first + || (!(__y.first < __x.first) && __x.second < __y.second); } + + /// Uses @c operator== to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x == __y); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __y < __x; } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__y < __x); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x < __y); } +#endif // !(three_way_comparison && concepts) + +#if __cplusplus >= 201103L + /** Swap overload for pairs. Calls std::pair::swap(). + * + * @note This std::swap overload is not declared in C++03 mode, + * which has performance implications, e.g. see https://gcc.gnu.org/PR38466 + */ + template + _GLIBCXX20_CONSTEXPR inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_T1>, + __is_swappable<_T2>>::value>::type +#else + void +#endif + swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __glibcxx_ranges_zip // >= C++23 + template + requires is_swappable_v && is_swappable_v + constexpr void + swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } +#endif // C++23 + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if, + __is_swappable<_T2>>::value>::type + swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; +#endif +#endif // __cplusplus >= 201103L + + /// @} relates pair + + /** + * @brief A convenience wrapper for creating a pair from two objects. + * @param __x The first object. + * @param __y The second object. + * @return A newly-constructed pair<> object of the appropriate type. + * + * The C++98 standard says the objects are passed by reference-to-const, + * but C++03 says they are passed by value (this was LWG issue #181). + * + * Since C++11 they have been passed by forwarding reference and then + * forwarded to the new members of the pair. To create a pair with a + * member of reference type, pass a `reference_wrapper` to this function. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 181. make_pair() unintended behavior +#if __cplusplus >= 201103L + // NB: DR 706. + template + constexpr pair::__type, + typename __decay_and_strip<_T2>::__type> + make_pair(_T1&& __x, _T2&& __y) + { + typedef typename __decay_and_strip<_T1>::__type __ds_type1; + typedef typename __decay_and_strip<_T2>::__type __ds_type2; + typedef pair<__ds_type1, __ds_type2> __pair_type; + return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); + } +#else + template + inline pair<_T1, _T2> + make_pair(_T1 __x, _T2 __y) + { return pair<_T1, _T2>(__x, __y); } +#endif + + /// @} + +#if __cplusplus >= 201103L + // Various functions which give std::pair a tuple-like interface. + + /// @cond undocumented + template + struct __is_tuple_like_impl> : true_type + { }; + /// @endcond + + /// Partial specialization for std::pair + template + struct tuple_size> + : public integral_constant { }; + + /// Partial specialization for std::pair + template + struct tuple_element<0, pair<_Tp1, _Tp2>> + { typedef _Tp1 type; }; + + /// Partial specialization for std::pair + template + struct tuple_element<1, pair<_Tp1, _Tp2>> + { typedef _Tp2 type; }; + + // Forward declare the partial specialization for std::tuple + // to work around modules bug PR c++/113814. + template + struct tuple_element<__i, tuple<_Types...>>; + +#if __cplusplus >= 201703L + template + inline constexpr size_t tuple_size_v> = 2; + + template + inline constexpr size_t tuple_size_v> = 2; + + template + inline constexpr bool __is_pair = false; + + template + inline constexpr bool __is_pair> = true; +#endif + + /// @cond undocumented + template + struct __pair_get; + + template<> + struct __pair_get<0> + { + template + static constexpr _Tp1& + __get(pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr _Tp1&& + __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp1>(__pair.first); } + + template + static constexpr const _Tp1& + __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr const _Tp1&& + __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.first); } + }; + + template<> + struct __pair_get<1> + { + template + static constexpr _Tp2& + __get(pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr _Tp2&& + __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp2>(__pair.second); } + + template + static constexpr const _Tp2& + __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr const _Tp2&& + __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.second); } + }; + /// @endcond + + /** @{ + * std::get overloads for accessing members of std::pair + */ + + template + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__get(__in); } + + template + constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__move_get(std::move(__in)); } + + template + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& + get(const pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__const_get(__in); } + + template + constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& + get(const pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__const_move_get(std::move(__in)); } + + +#ifdef __glibcxx_tuples_by_type // C++ >= 14 + template + constexpr _Tp& + get(pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr const _Tp& + get(const pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr _Tp&& + get(pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr _Tp& + get(pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr const _Tp& + get(const pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr _Tp&& + get(pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + + template + constexpr const _Tp&& + get(const pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } +#endif // __glibcxx_tuples_by_type + + +#if __glibcxx_ranges_zip // >= C++23 + template class _TQual, template class _UQual> + requires requires { typename pair, _UQual<_U1>>, + common_reference_t<_TQual<_T2>, _UQual<_U2>>>; } + struct basic_common_reference, pair<_U1, _U2>, _TQual, _UQual> + { + using type = pair, _UQual<_U1>>, + common_reference_t<_TQual<_T2>, _UQual<_U2>>>; + }; + + template + requires requires { typename pair, common_type_t<_T2, _U2>>; } + struct common_type, pair<_U1, _U2>> + { using type = pair, common_type_t<_T2, _U2>>; }; +#endif // C++23 + + /// @} +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_PAIR_H */ diff --git a/template/sysroot/include/bits/stl_raw_storage_iter.h b/template/sysroot/include/bits/stl_raw_storage_iter.h new file mode 100644 index 0000000..316dc5d --- /dev/null +++ b/template/sysroot/include/bits/stl_raw_storage_iter.h @@ -0,0 +1,128 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_raw_storage_iter.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_RAW_STORAGE_ITERATOR_H +#define _STL_RAW_STORAGE_ITERATOR_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +// Ignore warnings about std::iterator. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /** + * This iterator class lets algorithms store their results into + * uninitialized memory. + */ + template + class _GLIBCXX17_DEPRECATED raw_storage_iterator + : public iterator + { + protected: + _OutputIterator _M_iter; + + public: + explicit + raw_storage_iterator(_OutputIterator __x) + : _M_iter(__x) {} + + raw_storage_iterator& + operator*() { return *this; } + + raw_storage_iterator& + operator=(const _Tp& __element) + { + std::_Construct(std::__addressof(*_M_iter), __element); + return *this; + } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2127. Move-construction with raw_storage_iterator + raw_storage_iterator& + operator=(_Tp&& __element) + { + std::_Construct(std::__addressof(*_M_iter), std::move(__element)); + return *this; + } +#endif + + raw_storage_iterator& + operator++() + { + ++_M_iter; + return *this; + } + + raw_storage_iterator + operator++(int) + { + raw_storage_iterator __tmp = *this; + ++_M_iter; + return __tmp; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2454. Add raw_storage_iterator::base() member + _OutputIterator base() const { return _M_iter; } + }; +#pragma GCC diagnostic pop + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/bits/stl_relops.h b/template/sysroot/include/bits/stl_relops.h new file mode 100644 index 0000000..06c85ca --- /dev/null +++ b/template/sysroot/include/bits/stl_relops.h @@ -0,0 +1,134 @@ +// std::rel_ops implementation -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the, 2009 Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1996,1997 + * Silicon Graphics + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file bits/stl_relops.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + * + * This file is only included by ``, which is required by the + * standard to define namespace `rel_ops` and its contents. + */ + +#ifndef _STL_RELOPS_H +#define _STL_RELOPS_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace rel_ops + { + /** @namespace std::rel_ops + * @brief The generated relational operators are sequestered here. + * + * Libstdc++ headers must not use the contents of `rel_ops`. + * User code should also avoid them, because unconstrained function + * templates are too greedy and can easily cause ambiguities. + * + * C++20 default comparisons are a better solution. + */ + + /** + * @brief Defines @c != for arbitrary types, in terms of @c ==. + * @param __x A thing. + * @param __y Another thing. + * @return __x != __y + * + * This function uses @c == to determine its result. + */ + template + inline bool + operator!=(const _Tp& __x, const _Tp& __y) + { return !(__x == __y); } + + /** + * @brief Defines @c > for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x > __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>(const _Tp& __x, const _Tp& __y) + { return __y < __x; } + + /** + * @brief Defines @c <= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x <= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator<=(const _Tp& __x, const _Tp& __y) + { return !(__y < __x); } + + /** + * @brief Defines @c >= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x >= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>=(const _Tp& __x, const _Tp& __y) + { return !(__x < __y); } + } // namespace rel_ops + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_RELOPS_H */ diff --git a/template/sysroot/include/bits/stl_uninitialized.h b/template/sysroot/include/bits/stl_uninitialized.h new file mode 100644 index 0000000..7f84da3 --- /dev/null +++ b/template/sysroot/include/bits/stl_uninitialized.h @@ -0,0 +1,1158 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_UNINITIALIZED_H +#define _STL_UNINITIALIZED_H 1 + +#if __cplusplus >= 201103L +#include +#endif + +#include // copy +#include // __alloc_traits + +#if __cplusplus >= 201703L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @addtogroup memory + * @{ + */ + + /// @cond undocumented + +#if __cplusplus >= 201103L + template + constexpr bool + __check_constructible() + { + // Trivial types can have deleted constructors, but std::copy etc. + // only use assignment (or memmove) not construction, so we need an + // explicit check that construction from _Tp is actually valid, + // otherwise some ill-formed uses of std::uninitialized_xxx would + // compile without errors. This gives a nice clear error message. + static_assert(is_constructible<_ValueType, _Tp>::value, + "result type must be constructible from input type"); + + return true; + } + +// If the type is trivial we don't need to construct it, just assign to it. +// But trivial types can still have deleted or inaccessible assignment, +// so don't try to use std::copy or std::fill etc. if we can't assign. +# define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \ + __is_trivial(T) && __is_assignable(T&, U) \ + && std::__check_constructible() +#else +// No need to check if is_constructible for C++98. Trivial types have +// no user-declared constructors, so if the assignment is valid, construction +// should be too. +# define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \ + __is_trivial(T) && __is_assignable(T&, U) +#endif + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __do_uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + _ForwardIterator __cur = __result; + __try + { + for (; __first != __last; ++__first, (void)++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { return std::__do_uninit_copy(__first, __last, __result); } + }; + + template<> + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { return std::copy(__first, __last, __result); } + }; + + /// @endcond + + /** + * @brief Copies the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + * + * Like copy(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; + + // _ValueType1 must be trivially-copyable to use memmove, so don't + // bother optimizing to std::copy if it isn't. + // XXX Unnecessary because std::copy would check it anyway? + const bool __can_memmove = __is_trivial(_ValueType1); + +#if __cplusplus < 201103L + typedef typename iterator_traits<_InputIterator>::reference _From; +#else + using _From = decltype(*__first); +#endif + const bool __assignable + = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType2, _From); + + return std::__uninitialized_copy<__can_memmove && __assignable>:: + __uninit_copy(__first, __last, __result); + } + + /// @cond undocumented + + template + _GLIBCXX20_CONSTEXPR void + __do_uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + + template + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { std::__do_uninit_fill(__first, __last, __x); } + }; + + template<> + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { std::fill(__first, __last, __x); } + }; + + /// @endcond + + /** + * @brief Copies the value x into the range [first,last). + * @param __first An input iterator. + * @param __last An input iterator. + * @param __x The source value. + * @return Nothing. + * + * Like fill(), but does not require an initialized output range. + */ + template + inline void + uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + // Trivial types do not need a constructor to begin their lifetime, + // so try to use std::fill to benefit from its memset optimization. + const bool __can_fill + = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&); + + std::__uninitialized_fill<__can_fill>:: + __uninit_fill(__first, __last, __x); + } + + /// @cond undocumented + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __do_uninit_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + + template + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { return std::__do_uninit_fill_n(__first, __n, __x); } + }; + + template<> + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { return std::fill_n(__first, __n, __x); } + }; + + /// @endcond + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 1339. uninitialized_fill_n should return the end of its range + /** + * @brief Copies the value x into the range [first,first+n). + * @param __first An input iterator. + * @param __n The number of copies to make. + * @param __x The source value. + * @return Nothing. + * + * Like fill_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + // Trivial types do not need a constructor to begin their lifetime, + // so try to use std::fill_n to benefit from its optimizations. + const bool __can_fill + = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&) + // For arbitrary class types and floating point types we can't assume + // that __n > 0 and std::__size_to_integer(__n) > 0 are equivalent, + // so only use std::fill_n when _Size is already an integral type. + && __is_integer<_Size>::__value; + + return __uninitialized_fill_n<__can_fill>:: + __uninit_fill_n(__first, __n, __x); + } + +#undef _GLIBCXX_USE_ASSIGN_FOR_INIT + + /// @cond undocumented + + // Extensions: versions of uninitialized_copy, uninitialized_fill, + // and uninitialized_fill_n that take an allocator parameter. + // We dispatch back to the standard versions when we're given the + // default allocator. For nondefault allocators we do not use + // any of the POD optimizations. + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + _ForwardIterator __cur = __result; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __first != __last; ++__first, (void)++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur, __alloc); + __throw_exception_again; + } + } + +#if _GLIBCXX_HOSTED + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, allocator<_Tp>&) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__do_uninit_copy(__first, __last, __result); +#endif + return std::uninitialized_copy(__first, __last, __result); + } +#endif + + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_move_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), + __result, __alloc); + } + + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_move_if_noexcept_a(_InputIterator __first, + _InputIterator __last, + _ForwardIterator __result, + _Allocator& __alloc) + { + return std::__uninitialized_copy_a + (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc); + } + + template + _GLIBCXX20_CONSTEXPR + void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + +#if _GLIBCXX_HOSTED + template + _GLIBCXX20_CONSTEXPR + inline void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, allocator<_Tp2>&) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__do_uninit_fill(__first, __last, __x); +#endif + std::uninitialized_fill(__first, __last, __x); + } +#endif + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + +#if _GLIBCXX_HOSTED + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, allocator<_Tp2>&) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__do_uninit_fill_n(__first, __n, __x); +#endif + return std::uninitialized_fill_n(__first, __n, __x); + } +#endif + + // Extensions: __uninitialized_copy_move, __uninitialized_move_copy, + // __uninitialized_fill_move, __uninitialized_move_fill. + // All of these algorithms take a user-supplied allocator, which is used + // for construction and destruction. + + // __uninitialized_copy_move + // Copies [first1, last1) into [result, result + (last1 - first1)), and + // move [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_copy_move(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_copy + // Moves [first1, last1) into [result, result + (last1 - first1)), and + // copies [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_move_copy(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_fill_move + // Fills [result, mid) with x, and moves [first, last) into + // [mid, mid + (last - first)). + template + inline _ForwardIterator + __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid, + const _Tp& __x, _InputIterator __first, + _InputIterator __last, _Allocator& __alloc) + { + std::__uninitialized_fill_a(__result, __mid, __x, __alloc); + __try + { + return std::__uninitialized_move_a(__first, __last, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_fill + // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and + // fills [first2 + (last1 - first1), last2) with x. + template + inline void + __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, + _ForwardIterator __last2, const _Tp& __x, + _Allocator& __alloc) + { + _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1, + __first2, + __alloc); + __try + { + std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc); + } + __catch(...) + { + std::_Destroy(__first2, __mid2, __alloc); + __throw_exception_again; + } + } + + /// @endcond + +#if __cplusplus >= 201103L + /// @cond undocumented + + // Extensions: __uninitialized_default, __uninitialized_default_n, + // __uninitialized_default_a, __uninitialized_default_n_a. + + template + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + if (__first == __last) + return; + + typename iterator_traits<_ForwardIterator>::value_type* __val + = std::__addressof(*__first); + std::_Construct(__val); + if (++__first != __last) + std::fill(__first, __last, *__val); + } + }; + + template + struct __uninitialized_default_n_1 + { + template + _GLIBCXX20_CONSTEXPR + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_n_1 + { + template + _GLIBCXX20_CONSTEXPR + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + if (__n > 0) + { + typename iterator_traits<_ForwardIterator>::value_type* __val + = std::__addressof(*__first); + std::_Construct(__val); + ++__first; + __first = std::fill_n(__first, __n - 1, *__val); + } + return __first; + } + }; + + // __uninitialized_default + // Fills [first, last) with value-initialized value_types. + template + inline void + __uninitialized_default(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; + + std::__uninitialized_default_1<__is_trivial(_ValueType) + && __assignable>:: + __uninit_default(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with value-initialized value_types. + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_default_n(_ForwardIterator __first, _Size __n) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __uninitialized_default_n_1:: + __uninit_default_n(__first, __n); +#endif + + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // See uninitialized_fill_n for the conditions for using std::fill_n. + constexpr bool __can_fill + = __and_, is_copy_assignable<_ValueType>>::value; + + return __uninitialized_default_n_1<__is_trivial(_ValueType) + && __can_fill>:: + __uninit_default_n(__first, __n); + } + + + // __uninitialized_default_a + // Fills [first, last) with value_types constructed by the allocator + // alloc, with no arguments passed to the construct call. + template + void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + +#if _GLIBCXX_HOSTED + template + inline void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + allocator<_Tp>&) + { std::__uninitialized_default(__first, __last); } +#endif + + // __uninitialized_default_n_a + // Fills [first, first + n) with value_types constructed by the allocator + // alloc, with no arguments passed to the construct call. + template + _GLIBCXX20_CONSTEXPR _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + +#if _GLIBCXX_HOSTED + // __uninitialized_default_n_a specialization for std::allocator, + // which ignores the allocator and value-initializes the elements. + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + allocator<_Tp>&) + { return std::__uninitialized_default_n(__first, __n); } +#endif + + template + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator, _ForwardIterator) + { + } + }; + + template + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { return std::next(__first, __n); } + }; + + // __uninitialized_default_novalue + // Fills [first, last) with default-initialized value_types. + template + inline void + __uninitialized_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::__uninitialized_default_novalue_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue(__first, __last); + } + + // __uninitialized_default_novalue_n + // Fills [first, first + n) with default-initialized value_types. + template + inline _ForwardIterator + __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return __uninitialized_default_novalue_n_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue_n(__first, __n); + } + + template + _ForwardIterator + __uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { return std::uninitialized_copy(__first, __first + __n, __result); } + + template + pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return {__first, __cur}; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline pair<_RandomAccessIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { + auto __second_res = uninitialized_copy(__first, __first + __n, __result); + auto __first_res = std::next(__first, __n); + return {__first_res, __second_res}; + } + + /// @endcond + + /** + * @brief Copies the range [first,first+n) into result. + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return __result + __n + * @since C++11 + * + * Like copy_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { return std::__uninitialized_copy_n(__first, __n, __result, + std::__iterator_category(__first)); } + + /// @cond undocumented + template + inline pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { + return + std::__uninitialized_copy_n_pair(__first, __n, __result, + std::__iterator_category(__first)); + } + /// @endcond +#endif + +#ifdef __glibcxx_raw_memory_algorithms // C++ >= 17 + /** + * @brief Default-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + * @since C++17 + */ + template + inline void + uninitialized_default_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + __uninitialized_default_novalue(__first, __last); + } + + /** + * @brief Default-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __first + __count + * @since C++17 + */ + template + inline _ForwardIterator + uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_novalue_n(__first, __count); + } + + /** + * @brief Value-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + * @since C++17 + */ + template + inline void + uninitialized_value_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + return __uninitialized_default(__first, __last); + } + + /** + * @brief Value-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __result + __count + * @since C++17 + */ + template + inline _ForwardIterator + uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_n(__first, __count); + } + + /** + * @brief Move-construct from the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + * @since C++17 + */ + template + inline _ForwardIterator + uninitialized_move(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + return std::uninitialized_copy + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); + } + + /** + * @brief Move-construct from the range [first,first+count) into result. + * @param __first An input iterator. + * @param __count The number of objects to initialize. + * @param __result An output iterator. + * @return __result + __count + * @since C++17 + */ + template + inline pair<_InputIterator, _ForwardIterator> + uninitialized_move_n(_InputIterator __first, _Size __count, + _ForwardIterator __result) + { + auto __res = std::__uninitialized_copy_n_pair + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + __count, __result); + return {__res.first.base(), __res.second}; + } +#endif // __glibcxx_raw_memory_algorithms + +#if __cplusplus >= 201103L + /// @cond undocumented + + template + _GLIBCXX20_CONSTEXPR + inline void + __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig, + _Allocator& __alloc) + noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, + __dest, std::move(*__orig))) + && noexcept(std::allocator_traits<_Allocator>::destroy( + __alloc, std::__addressof(*__orig)))) + { + typedef std::allocator_traits<_Allocator> __traits; + __traits::construct(__alloc, __dest, std::move(*__orig)); + __traits::destroy(__alloc, std::__addressof(*__orig)); + } + + // This class may be specialized for specific types. + // Also known as is_trivially_relocatable. + template + struct __is_bitwise_relocatable + : is_trivial<_Tp> { }; + + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __relocate_a_1(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(std::__relocate_object_a(std::addressof(*__result), + std::addressof(*__first), + __alloc))) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; + static_assert(std::is_same<_ValueType, _ValueType2>::value, + "relocation is only possible for values of the same type"); + _ForwardIterator __cur = __result; + for (; __first != __last; ++__first, (void)++__cur) + std::__relocate_object_a(std::__addressof(*__cur), + std::__addressof(*__first), __alloc); + return __cur; + } + +#if _GLIBCXX_HOSTED + template + _GLIBCXX20_CONSTEXPR + inline __enable_if_t::value, _Tp*> + __relocate_a_1(_Tp* __first, _Tp* __last, + _Tp* __result, + [[__maybe_unused__]] allocator<_Up>& __alloc) noexcept + { + ptrdiff_t __count = __last - __first; + if (__count > 0) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + // Can't use memcpy. Wrap the pointer so that __relocate_a_1 + // resolves to the non-trivial overload above. + __gnu_cxx::__normal_iterator<_Tp*, void> __out(__result); + __out = std::__relocate_a_1(__first, __last, __out, __alloc); + return __out.base(); + } +#endif + __builtin_memcpy(__result, __first, __count * sizeof(_Tp)); + } + return __result + __count; + } +#endif + + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + __relocate_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(__relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc))) + { + return std::__relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc); + } + + /// @endcond +#endif // C++11 + + /// @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_UNINITIALIZED_H */ diff --git a/template/sysroot/include/bits/string_view.tcc b/template/sysroot/include/bits/string_view.tcc new file mode 100644 index 0000000..5fa5049 --- /dev/null +++ b/template/sysroot/include/bits/string_view.tcc @@ -0,0 +1,241 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/string_view.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string_view} + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW_TCC +#define _GLIBCXX_STRING_VIEW_TCC 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n == 0) + return __pos <= _M_len ? __pos : npos; + if (__pos >= _M_len) + return npos; + + const _CharT __elem0 = __str[0]; + const _CharT* __first = _M_str + __pos; + const _CharT* const __last = _M_str + _M_len; + size_type __len = _M_len - __pos; + + while (__len >= __n) + { + // Find the first occurrence of __elem0: + __first = traits_type::find(__first, __len - __n + 1, __elem0); + if (!__first) + return npos; + // Compare the full strings from the first occurrence of __elem0. + // We already know that __first[0] == __s[0] but compare them again + // anyway because __s is probably aligned, which helps memcmp. + if (traits_type::compare(__first, __str, __n) == 0) + return __first - _M_str; + __len = __last - ++__first; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(_CharT __c, size_type __pos) const noexcept + { + size_type __ret = npos; + if (__pos < this->_M_len) + { + const size_type __n = this->_M_len - __pos; + const _CharT* __p = traits_type::find(this->_M_str + __pos, __n, __c); + if (__p) + __ret = __p - this->_M_str; + } + return __ret; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n <= this->_M_len) + { + __pos = std::min(size_type(this->_M_len - __n), __pos); + do + { + if (traits_type::compare(this->_M_str + __pos, __str, __n) == 0) + return __pos; + } + while (__pos-- > 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size > 0) + { + if (--__size > __pos) + __size = __pos; + for (++__size; __size-- > 0; ) + if (traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __n && __pos < this->_M_len; ++__pos) + { + const _CharT* __p = traits_type::find(__str, __n, + this->_M_str[__pos]); + if (__p) + return __pos; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->size(); + if (__size && __n) + { + if (--__size > __pos) + __size = __pos; + do + { + if (traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size-- != 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::find(__str, __n, this->_M_str[__pos])) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(_CharT __c, size_type __pos) const noexcept + { + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::eq(this->_M_str[__pos], __c)) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size--); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + while (__size--); + } + return npos; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_STRING_VIEW_TCC diff --git a/template/sysroot/include/bits/text_encoding-data.h b/template/sysroot/include/bits/text_encoding-data.h new file mode 100644 index 0000000..d6c34f8 --- /dev/null +++ b/template/sysroot/include/bits/text_encoding-data.h @@ -0,0 +1,931 @@ +// Generated by scripts/gen_text_encoding_data.py, do not edit. + + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/text_encoding-data.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{text_encoding} + */ + +#ifndef _GLIBCXX_GET_ENCODING_DATA +# error "This is not a public header, do not include it directly" +#endif + + { 3, "US-ASCII" }, + { 3, "iso-ir-6" }, + { 3, "ANSI_X3.4-1968" }, + { 3, "ANSI_X3.4-1986" }, + { 3, "ISO_646.irv:1991" }, + { 3, "ISO646-US" }, + { 3, "us" }, + { 3, "IBM367" }, + { 3, "cp367" }, + { 3, "csASCII" }, + { 3, "ASCII" }, // libstdc++ extension + { 4, "ISO_8859-1:1987" }, + { 4, "iso-ir-100" }, + { 4, "ISO_8859-1" }, + { 4, "ISO-8859-1" }, + { 4, "latin1" }, + { 4, "l1" }, + { 4, "IBM819" }, + { 4, "CP819" }, + { 4, "csISOLatin1" }, + { 5, "ISO_8859-2:1987" }, + { 5, "iso-ir-101" }, + { 5, "ISO_8859-2" }, + { 5, "ISO-8859-2" }, + { 5, "latin2" }, + { 5, "l2" }, + { 5, "csISOLatin2" }, + { 6, "ISO_8859-3:1988" }, + { 6, "iso-ir-109" }, + { 6, "ISO_8859-3" }, + { 6, "ISO-8859-3" }, + { 6, "latin3" }, + { 6, "l3" }, + { 6, "csISOLatin3" }, + { 7, "ISO_8859-4:1988" }, + { 7, "iso-ir-110" }, + { 7, "ISO_8859-4" }, + { 7, "ISO-8859-4" }, + { 7, "latin4" }, + { 7, "l4" }, + { 7, "csISOLatin4" }, + { 8, "ISO_8859-5:1988" }, + { 8, "iso-ir-144" }, + { 8, "ISO_8859-5" }, + { 8, "ISO-8859-5" }, + { 8, "cyrillic" }, + { 8, "csISOLatinCyrillic" }, + { 9, "ISO_8859-6:1987" }, + { 9, "iso-ir-127" }, + { 9, "ISO_8859-6" }, + { 9, "ISO-8859-6" }, + { 9, "ECMA-114" }, + { 9, "ASMO-708" }, + { 9, "arabic" }, + { 9, "csISOLatinArabic" }, + { 10, "ISO_8859-7:1987" }, + { 10, "iso-ir-126" }, + { 10, "ISO_8859-7" }, + { 10, "ISO-8859-7" }, + { 10, "ELOT_928" }, + { 10, "ECMA-118" }, + { 10, "greek" }, + { 10, "greek8" }, + { 10, "csISOLatinGreek" }, + { 11, "ISO_8859-8:1988" }, + { 11, "iso-ir-138" }, + { 11, "ISO_8859-8" }, + { 11, "ISO-8859-8" }, + { 11, "hebrew" }, + { 11, "csISOLatinHebrew" }, + { 12, "ISO_8859-9:1989" }, + { 12, "iso-ir-148" }, + { 12, "ISO_8859-9" }, + { 12, "ISO-8859-9" }, + { 12, "latin5" }, + { 12, "l5" }, + { 12, "csISOLatin5" }, + { 13, "ISO-8859-10" }, + { 13, "iso-ir-157" }, + { 13, "l6" }, + { 13, "ISO_8859-10:1992" }, + { 13, "csISOLatin6" }, + { 13, "latin6" }, + { 14, "ISO_6937-2-add" }, + { 14, "iso-ir-142" }, + { 14, "csISOTextComm" }, + { 15, "JIS_X0201" }, + { 15, "X0201" }, + { 15, "csHalfWidthKatakana" }, + { 16, "JIS_Encoding" }, + { 16, "csJISEncoding" }, + { 17, "Shift_JIS" }, + { 17, "MS_Kanji" }, + { 17, "csShiftJIS" }, + { 18, "Extended_UNIX_Code_Packed_Format_for_Japanese" }, + { 18, "csEUCPkdFmtJapanese" }, + { 18, "EUC-JP" }, + { 19, "Extended_UNIX_Code_Fixed_Width_for_Japanese" }, + { 19, "csEUCFixWidJapanese" }, + { 20, "BS_4730" }, + { 20, "iso-ir-4" }, + { 20, "ISO646-GB" }, + { 20, "gb" }, + { 20, "uk" }, + { 20, "csISO4UnitedKingdom" }, + { 21, "SEN_850200_C" }, + { 21, "iso-ir-11" }, + { 21, "ISO646-SE2" }, + { 21, "se2" }, + { 21, "csISO11SwedishForNames" }, + { 22, "IT" }, + { 22, "iso-ir-15" }, + { 22, "ISO646-IT" }, + { 22, "csISO15Italian" }, + { 23, "ES" }, + { 23, "iso-ir-17" }, + { 23, "ISO646-ES" }, + { 23, "csISO17Spanish" }, + { 24, "DIN_66003" }, + { 24, "iso-ir-21" }, + { 24, "de" }, + { 24, "ISO646-DE" }, + { 24, "csISO21German" }, + { 25, "NS_4551-1" }, + { 25, "iso-ir-60" }, + { 25, "ISO646-NO" }, + { 25, "no" }, + { 25, "csISO60DanishNorwegian" }, + { 25, "csISO60Norwegian1" }, + { 26, "NF_Z_62-010" }, + { 26, "iso-ir-69" }, + { 26, "ISO646-FR" }, + { 26, "fr" }, + { 26, "csISO69French" }, + { 27, "ISO-10646-UTF-1" }, + { 27, "csISO10646UTF1" }, + { 28, "ISO_646.basic:1983" }, + { 28, "ref" }, + { 28, "csISO646basic1983" }, + { 29, "INVARIANT" }, + { 29, "csINVARIANT" }, + { 30, "ISO_646.irv:1983" }, + { 30, "iso-ir-2" }, + { 30, "irv" }, + { 30, "csISO2IntlRefVersion" }, + { 31, "NATS-SEFI" }, + { 31, "iso-ir-8-1" }, + { 31, "csNATSSEFI" }, + { 32, "NATS-SEFI-ADD" }, + { 32, "iso-ir-8-2" }, + { 32, "csNATSSEFIADD" }, + { 35, "SEN_850200_B" }, + { 35, "iso-ir-10" }, + { 35, "FI" }, + { 35, "ISO646-FI" }, + { 35, "ISO646-SE" }, + { 35, "se" }, + { 35, "csISO10Swedish" }, + { 36, "KS_C_5601-1987" }, + { 36, "iso-ir-149" }, + { 36, "KS_C_5601-1989" }, + { 36, "KSC_5601" }, + { 36, "korean" }, + { 36, "csKSC56011987" }, + { 37, "ISO-2022-KR" }, + { 37, "csISO2022KR" }, + { 38, "EUC-KR" }, + { 38, "csEUCKR" }, + { 39, "ISO-2022-JP" }, + { 39, "csISO2022JP" }, + { 40, "ISO-2022-JP-2" }, + { 40, "csISO2022JP2" }, + { 41, "JIS_C6220-1969-jp" }, + { 41, "JIS_C6220-1969" }, + { 41, "iso-ir-13" }, + { 41, "katakana" }, + { 41, "x0201-7" }, + { 41, "csISO13JISC6220jp" }, + { 42, "JIS_C6220-1969-ro" }, + { 42, "iso-ir-14" }, + { 42, "jp" }, + { 42, "ISO646-JP" }, + { 42, "csISO14JISC6220ro" }, + { 43, "PT" }, + { 43, "iso-ir-16" }, + { 43, "ISO646-PT" }, + { 43, "csISO16Portuguese" }, + { 44, "greek7-old" }, + { 44, "iso-ir-18" }, + { 44, "csISO18Greek7Old" }, + { 45, "latin-greek" }, + { 45, "iso-ir-19" }, + { 45, "csISO19LatinGreek" }, + { 46, "NF_Z_62-010_(1973)" }, + { 46, "iso-ir-25" }, + { 46, "ISO646-FR1" }, + { 46, "csISO25French" }, + { 47, "Latin-greek-1" }, + { 47, "iso-ir-27" }, + { 47, "csISO27LatinGreek1" }, + { 48, "ISO_5427" }, + { 48, "iso-ir-37" }, + { 48, "csISO5427Cyrillic" }, + { 49, "JIS_C6226-1978" }, + { 49, "iso-ir-42" }, + { 49, "csISO42JISC62261978" }, + { 50, "BS_viewdata" }, + { 50, "iso-ir-47" }, + { 50, "csISO47BSViewdata" }, + { 51, "INIS" }, + { 51, "iso-ir-49" }, + { 51, "csISO49INIS" }, + { 52, "INIS-8" }, + { 52, "iso-ir-50" }, + { 52, "csISO50INIS8" }, + { 53, "INIS-cyrillic" }, + { 53, "iso-ir-51" }, + { 53, "csISO51INISCyrillic" }, + { 54, "ISO_5427:1981" }, + { 54, "iso-ir-54" }, + { 54, "ISO5427Cyrillic1981" }, + { 54, "csISO54271981" }, + { 55, "ISO_5428:1980" }, + { 55, "iso-ir-55" }, + { 55, "csISO5428Greek" }, + { 56, "GB_1988-80" }, + { 56, "iso-ir-57" }, + { 56, "cn" }, + { 56, "ISO646-CN" }, + { 56, "csISO57GB1988" }, + { 57, "GB_2312-80" }, + { 57, "iso-ir-58" }, + { 57, "chinese" }, + { 57, "csISO58GB231280" }, + { 58, "NS_4551-2" }, + { 58, "ISO646-NO2" }, + { 58, "iso-ir-61" }, + { 58, "no2" }, + { 58, "csISO61Norwegian2" }, + { 59, "videotex-suppl" }, + { 59, "iso-ir-70" }, + { 59, "csISO70VideotexSupp1" }, + { 60, "PT2" }, + { 60, "iso-ir-84" }, + { 60, "ISO646-PT2" }, + { 60, "csISO84Portuguese2" }, + { 61, "ES2" }, + { 61, "iso-ir-85" }, + { 61, "ISO646-ES2" }, + { 61, "csISO85Spanish2" }, + { 62, "MSZ_7795.3" }, + { 62, "iso-ir-86" }, + { 62, "ISO646-HU" }, + { 62, "hu" }, + { 62, "csISO86Hungarian" }, + { 63, "JIS_C6226-1983" }, + { 63, "iso-ir-87" }, + { 63, "x0208" }, + { 63, "JIS_X0208-1983" }, + { 63, "csISO87JISX0208" }, + { 64, "greek7" }, + { 64, "iso-ir-88" }, + { 64, "csISO88Greek7" }, + { 65, "ASMO_449" }, + { 65, "ISO_9036" }, + { 65, "arabic7" }, + { 65, "iso-ir-89" }, + { 65, "csISO89ASMO449" }, + { 66, "iso-ir-90" }, + { 66, "csISO90" }, + { 67, "JIS_C6229-1984-a" }, + { 67, "iso-ir-91" }, + { 67, "jp-ocr-a" }, + { 67, "csISO91JISC62291984a" }, + { 68, "JIS_C6229-1984-b" }, + { 68, "iso-ir-92" }, + { 68, "ISO646-JP-OCR-B" }, + { 68, "jp-ocr-b" }, + { 68, "csISO92JISC62991984b" }, + { 69, "JIS_C6229-1984-b-add" }, + { 69, "iso-ir-93" }, + { 69, "jp-ocr-b-add" }, + { 69, "csISO93JIS62291984badd" }, + { 70, "JIS_C6229-1984-hand" }, + { 70, "iso-ir-94" }, + { 70, "jp-ocr-hand" }, + { 70, "csISO94JIS62291984hand" }, + { 71, "JIS_C6229-1984-hand-add" }, + { 71, "iso-ir-95" }, + { 71, "jp-ocr-hand-add" }, + { 71, "csISO95JIS62291984handadd" }, + { 72, "JIS_C6229-1984-kana" }, + { 72, "iso-ir-96" }, + { 72, "csISO96JISC62291984kana" }, + { 73, "ISO_2033-1983" }, + { 73, "iso-ir-98" }, + { 73, "e13b" }, + { 73, "csISO2033" }, + { 74, "ANSI_X3.110-1983" }, + { 74, "iso-ir-99" }, + { 74, "CSA_T500-1983" }, + { 74, "NAPLPS" }, + { 74, "csISO99NAPLPS" }, + { 75, "T.61-7bit" }, + { 75, "iso-ir-102" }, + { 75, "csISO102T617bit" }, + { 76, "T.61-8bit" }, + { 76, "T.61" }, + { 76, "iso-ir-103" }, + { 76, "csISO103T618bit" }, + { 77, "ECMA-cyrillic" }, + { 77, "iso-ir-111" }, + { 77, "KOI8-E" }, + { 77, "csISO111ECMACyrillic" }, + { 78, "CSA_Z243.4-1985-1" }, + { 78, "iso-ir-121" }, + { 78, "ISO646-CA" }, + { 78, "csa7-1" }, + { 78, "csa71" }, + { 78, "ca" }, + { 78, "csISO121Canadian1" }, + { 79, "CSA_Z243.4-1985-2" }, + { 79, "iso-ir-122" }, + { 79, "ISO646-CA2" }, + { 79, "csa7-2" }, + { 79, "csa72" }, + { 79, "csISO122Canadian2" }, + { 80, "CSA_Z243.4-1985-gr" }, + { 80, "iso-ir-123" }, + { 80, "csISO123CSAZ24341985gr" }, + { 81, "ISO_8859-6-E" }, + { 81, "csISO88596E" }, + { 81, "ISO-8859-6-E" }, + { 82, "ISO_8859-6-I" }, + { 82, "csISO88596I" }, + { 82, "ISO-8859-6-I" }, + { 83, "T.101-G2" }, + { 83, "iso-ir-128" }, + { 83, "csISO128T101G2" }, + { 84, "ISO_8859-8-E" }, + { 84, "csISO88598E" }, + { 84, "ISO-8859-8-E" }, + { 85, "ISO_8859-8-I" }, + { 85, "csISO88598I" }, + { 85, "ISO-8859-8-I" }, + { 86, "CSN_369103" }, + { 86, "iso-ir-139" }, + { 86, "csISO139CSN369103" }, + { 87, "JUS_I.B1.002" }, + { 87, "iso-ir-141" }, + { 87, "ISO646-YU" }, + { 87, "js" }, + { 87, "yu" }, + { 87, "csISO141JUSIB1002" }, + { 88, "IEC_P27-1" }, + { 88, "iso-ir-143" }, + { 88, "csISO143IECP271" }, + { 89, "JUS_I.B1.003-serb" }, + { 89, "iso-ir-146" }, + { 89, "serbian" }, + { 89, "csISO146Serbian" }, + { 90, "JUS_I.B1.003-mac" }, + { 90, "macedonian" }, + { 90, "iso-ir-147" }, + { 90, "csISO147Macedonian" }, + { 91, "greek-ccitt" }, + { 91, "iso-ir-150" }, + { 91, "csISO150" }, + { 91, "csISO150GreekCCITT" }, + { 92, "NC_NC00-10:81" }, + { 92, "cuba" }, + { 92, "iso-ir-151" }, + { 92, "ISO646-CU" }, + { 92, "csISO151Cuba" }, + { 93, "ISO_6937-2-25" }, + { 93, "iso-ir-152" }, + { 93, "csISO6937Add" }, + { 94, "GOST_19768-74" }, + { 94, "ST_SEV_358-88" }, + { 94, "iso-ir-153" }, + { 94, "csISO153GOST1976874" }, + { 95, "ISO_8859-supp" }, + { 95, "iso-ir-154" }, + { 95, "latin1-2-5" }, + { 95, "csISO8859Supp" }, + { 96, "ISO_10367-box" }, + { 96, "iso-ir-155" }, + { 96, "csISO10367Box" }, + { 97, "latin-lap" }, + { 97, "lap" }, + { 97, "iso-ir-158" }, + { 97, "csISO158Lap" }, + { 98, "JIS_X0212-1990" }, + { 98, "x0212" }, + { 98, "iso-ir-159" }, + { 98, "csISO159JISX02121990" }, + { 99, "DS_2089" }, + { 99, "DS2089" }, + { 99, "ISO646-DK" }, + { 99, "dk" }, + { 99, "csISO646Danish" }, + { 100, "us-dk" }, + { 100, "csUSDK" }, + { 101, "dk-us" }, + { 101, "csDKUS" }, + { 102, "KSC5636" }, + { 102, "ISO646-KR" }, + { 102, "csKSC5636" }, + { 103, "UNICODE-1-1-UTF-7" }, + { 103, "csUnicode11UTF7" }, + { 104, "ISO-2022-CN" }, + { 104, "csISO2022CN" }, + { 105, "ISO-2022-CN-EXT" }, + { 105, "csISO2022CNEXT" }, +#define _GLIBCXX_TEXT_ENCODING_UTF8_OFFSET 414 + { 106, "UTF-8" }, + { 106, "csUTF8" }, + { 109, "ISO-8859-13" }, + { 109, "csISO885913" }, + { 110, "ISO-8859-14" }, + { 110, "iso-ir-199" }, + { 110, "ISO_8859-14:1998" }, + { 110, "ISO_8859-14" }, + { 110, "latin8" }, + { 110, "iso-celtic" }, + { 110, "l8" }, + { 110, "csISO885914" }, + { 111, "ISO-8859-15" }, + { 111, "ISO_8859-15" }, + { 111, "Latin-9" }, + { 111, "csISO885915" }, + { 112, "ISO-8859-16" }, + { 112, "iso-ir-226" }, + { 112, "ISO_8859-16:2001" }, + { 112, "ISO_8859-16" }, + { 112, "latin10" }, + { 112, "l10" }, + { 112, "csISO885916" }, + { 113, "GBK" }, + { 113, "CP936" }, + { 113, "MS936" }, + { 113, "windows-936" }, + { 113, "csGBK" }, + { 114, "GB18030" }, + { 114, "csGB18030" }, + { 115, "OSD_EBCDIC_DF04_15" }, + { 115, "csOSDEBCDICDF0415" }, + { 116, "OSD_EBCDIC_DF03_IRV" }, + { 116, "csOSDEBCDICDF03IRV" }, + { 117, "OSD_EBCDIC_DF04_1" }, + { 117, "csOSDEBCDICDF041" }, + { 118, "ISO-11548-1" }, + { 118, "ISO_11548-1" }, + { 118, "ISO_TR_11548-1" }, + { 118, "csISO115481" }, + { 119, "KZ-1048" }, + { 119, "STRK1048-2002" }, + { 119, "RK1048" }, + { 119, "csKZ1048" }, + { 1000, "ISO-10646-UCS-2" }, + { 1000, "csUnicode" }, + { 1001, "ISO-10646-UCS-4" }, + { 1001, "csUCS4" }, + { 1002, "ISO-10646-UCS-Basic" }, + { 1002, "csUnicodeASCII" }, + { 1003, "ISO-10646-Unicode-Latin1" }, + { 1003, "csUnicodeLatin1" }, + { 1003, "ISO-10646" }, + { 1004, "ISO-10646-J-1" }, + { 1004, "csUnicodeJapanese" }, + { 1005, "ISO-Unicode-IBM-1261" }, + { 1005, "csUnicodeIBM1261" }, + { 1006, "ISO-Unicode-IBM-1268" }, + { 1006, "csUnicodeIBM1268" }, + { 1007, "ISO-Unicode-IBM-1276" }, + { 1007, "csUnicodeIBM1276" }, + { 1008, "ISO-Unicode-IBM-1264" }, + { 1008, "csUnicodeIBM1264" }, + { 1009, "ISO-Unicode-IBM-1265" }, + { 1009, "csUnicodeIBM1265" }, + { 1010, "UNICODE-1-1" }, + { 1010, "csUnicode11" }, + { 1011, "SCSU" }, + { 1011, "csSCSU" }, + { 1012, "UTF-7" }, + { 1012, "csUTF7" }, + { 1013, "UTF-16BE" }, + { 1013, "csUTF16BE" }, + { 1014, "UTF-16LE" }, + { 1014, "csUTF16LE" }, + { 1015, "UTF-16" }, + { 1015, "csUTF16" }, + { 1016, "CESU-8" }, + { 1016, "csCESU8" }, + { 1016, "csCESU-8" }, + { 1017, "UTF-32" }, + { 1017, "csUTF32" }, + { 1018, "UTF-32BE" }, + { 1018, "csUTF32BE" }, + { 1019, "UTF-32LE" }, + { 1019, "csUTF32LE" }, + { 1020, "BOCU-1" }, + { 1020, "csBOCU1" }, + { 1020, "csBOCU-1" }, + { 1021, "UTF-7-IMAP" }, + { 1021, "csUTF7IMAP" }, + { 2000, "ISO-8859-1-Windows-3.0-Latin-1" }, + { 2000, "csWindows30Latin1" }, + { 2001, "ISO-8859-1-Windows-3.1-Latin-1" }, + { 2001, "csWindows31Latin1" }, + { 2002, "ISO-8859-2-Windows-Latin-2" }, + { 2002, "csWindows31Latin2" }, + { 2003, "ISO-8859-9-Windows-Latin-5" }, + { 2003, "csWindows31Latin5" }, + { 2004, "hp-roman8" }, + { 2004, "roman8" }, + { 2004, "r8" }, + { 2004, "csHPRoman8" }, + { 2005, "Adobe-Standard-Encoding" }, + { 2005, "csAdobeStandardEncoding" }, + { 2006, "Ventura-US" }, + { 2006, "csVenturaUS" }, + { 2007, "Ventura-International" }, + { 2007, "csVenturaInternational" }, + { 2008, "DEC-MCS" }, + { 2008, "dec" }, + { 2008, "csDECMCS" }, + { 2009, "IBM850" }, + { 2009, "cp850" }, + { 2009, "850" }, + { 2009, "csPC850Multilingual" }, + { 2010, "IBM852" }, + { 2010, "cp852" }, + { 2010, "852" }, + { 2010, "csPCp852" }, + { 2011, "IBM437" }, + { 2011, "cp437" }, + { 2011, "437" }, + { 2011, "csPC8CodePage437" }, + { 2012, "PC8-Danish-Norwegian" }, + { 2012, "csPC8DanishNorwegian" }, + { 2013, "IBM862" }, + { 2013, "cp862" }, + { 2013, "862" }, + { 2013, "csPC862LatinHebrew" }, + { 2014, "PC8-Turkish" }, + { 2014, "csPC8Turkish" }, + { 2015, "IBM-Symbols" }, + { 2015, "csIBMSymbols" }, + { 2016, "IBM-Thai" }, + { 2016, "csIBMThai" }, + { 2017, "HP-Legal" }, + { 2017, "csHPLegal" }, + { 2018, "HP-Pi-font" }, + { 2018, "csHPPiFont" }, + { 2019, "HP-Math8" }, + { 2019, "csHPMath8" }, + { 2020, "Adobe-Symbol-Encoding" }, + { 2020, "csHPPSMath" }, + { 2021, "HP-DeskTop" }, + { 2021, "csHPDesktop" }, + { 2022, "Ventura-Math" }, + { 2022, "csVenturaMath" }, + { 2023, "Microsoft-Publishing" }, + { 2023, "csMicrosoftPublishing" }, + { 2024, "Windows-31J" }, + { 2024, "csWindows31J" }, + { 2025, "GB2312" }, + { 2025, "csGB2312" }, + { 2026, "Big5" }, + { 2026, "csBig5" }, + { 2027, "macintosh" }, + { 2027, "mac" }, + { 2027, "csMacintosh" }, + { 2028, "IBM037" }, + { 2028, "cp037" }, + { 2028, "ebcdic-cp-us" }, + { 2028, "ebcdic-cp-ca" }, + { 2028, "ebcdic-cp-wt" }, + { 2028, "ebcdic-cp-nl" }, + { 2028, "csIBM037" }, + { 2029, "IBM038" }, + { 2029, "EBCDIC-INT" }, + { 2029, "cp038" }, + { 2029, "csIBM038" }, + { 2030, "IBM273" }, + { 2030, "CP273" }, + { 2030, "csIBM273" }, + { 2031, "IBM274" }, + { 2031, "EBCDIC-BE" }, + { 2031, "CP274" }, + { 2031, "csIBM274" }, + { 2032, "IBM275" }, + { 2032, "EBCDIC-BR" }, + { 2032, "cp275" }, + { 2032, "csIBM275" }, + { 2033, "IBM277" }, + { 2033, "EBCDIC-CP-DK" }, + { 2033, "EBCDIC-CP-NO" }, + { 2033, "csIBM277" }, + { 2034, "IBM278" }, + { 2034, "CP278" }, + { 2034, "ebcdic-cp-fi" }, + { 2034, "ebcdic-cp-se" }, + { 2034, "csIBM278" }, + { 2035, "IBM280" }, + { 2035, "CP280" }, + { 2035, "ebcdic-cp-it" }, + { 2035, "csIBM280" }, + { 2036, "IBM281" }, + { 2036, "EBCDIC-JP-E" }, + { 2036, "cp281" }, + { 2036, "csIBM281" }, + { 2037, "IBM284" }, + { 2037, "CP284" }, + { 2037, "ebcdic-cp-es" }, + { 2037, "csIBM284" }, + { 2038, "IBM285" }, + { 2038, "CP285" }, + { 2038, "ebcdic-cp-gb" }, + { 2038, "csIBM285" }, + { 2039, "IBM290" }, + { 2039, "cp290" }, + { 2039, "EBCDIC-JP-kana" }, + { 2039, "csIBM290" }, + { 2040, "IBM297" }, + { 2040, "cp297" }, + { 2040, "ebcdic-cp-fr" }, + { 2040, "csIBM297" }, + { 2041, "IBM420" }, + { 2041, "cp420" }, + { 2041, "ebcdic-cp-ar1" }, + { 2041, "csIBM420" }, + { 2042, "IBM423" }, + { 2042, "cp423" }, + { 2042, "ebcdic-cp-gr" }, + { 2042, "csIBM423" }, + { 2043, "IBM424" }, + { 2043, "cp424" }, + { 2043, "ebcdic-cp-he" }, + { 2043, "csIBM424" }, + { 2044, "IBM500" }, + { 2044, "CP500" }, + { 2044, "ebcdic-cp-be" }, + { 2044, "ebcdic-cp-ch" }, + { 2044, "csIBM500" }, + { 2045, "IBM851" }, + { 2045, "cp851" }, + { 2045, "851" }, + { 2045, "csIBM851" }, + { 2046, "IBM855" }, + { 2046, "cp855" }, + { 2046, "855" }, + { 2046, "csIBM855" }, + { 2047, "IBM857" }, + { 2047, "cp857" }, + { 2047, "857" }, + { 2047, "csIBM857" }, + { 2048, "IBM860" }, + { 2048, "cp860" }, + { 2048, "860" }, + { 2048, "csIBM860" }, + { 2049, "IBM861" }, + { 2049, "cp861" }, + { 2049, "861" }, + { 2049, "cp-is" }, + { 2049, "csIBM861" }, + { 2050, "IBM863" }, + { 2050, "cp863" }, + { 2050, "863" }, + { 2050, "csIBM863" }, + { 2051, "IBM864" }, + { 2051, "cp864" }, + { 2051, "csIBM864" }, + { 2052, "IBM865" }, + { 2052, "cp865" }, + { 2052, "865" }, + { 2052, "csIBM865" }, + { 2053, "IBM868" }, + { 2053, "CP868" }, + { 2053, "cp-ar" }, + { 2053, "csIBM868" }, + { 2054, "IBM869" }, + { 2054, "cp869" }, + { 2054, "869" }, + { 2054, "cp-gr" }, + { 2054, "csIBM869" }, + { 2055, "IBM870" }, + { 2055, "CP870" }, + { 2055, "ebcdic-cp-roece" }, + { 2055, "ebcdic-cp-yu" }, + { 2055, "csIBM870" }, + { 2056, "IBM871" }, + { 2056, "CP871" }, + { 2056, "ebcdic-cp-is" }, + { 2056, "csIBM871" }, + { 2057, "IBM880" }, + { 2057, "cp880" }, + { 2057, "EBCDIC-Cyrillic" }, + { 2057, "csIBM880" }, + { 2058, "IBM891" }, + { 2058, "cp891" }, + { 2058, "csIBM891" }, + { 2059, "IBM903" }, + { 2059, "cp903" }, + { 2059, "csIBM903" }, + { 2060, "IBM904" }, + { 2060, "cp904" }, + { 2060, "904" }, + { 2060, "csIBBM904" }, + { 2061, "IBM905" }, + { 2061, "CP905" }, + { 2061, "ebcdic-cp-tr" }, + { 2061, "csIBM905" }, + { 2062, "IBM918" }, + { 2062, "CP918" }, + { 2062, "ebcdic-cp-ar2" }, + { 2062, "csIBM918" }, + { 2063, "IBM1026" }, + { 2063, "CP1026" }, + { 2063, "csIBM1026" }, + { 2064, "EBCDIC-AT-DE" }, + { 2064, "csIBMEBCDICATDE" }, + { 2065, "EBCDIC-AT-DE-A" }, + { 2065, "csEBCDICATDEA" }, + { 2066, "EBCDIC-CA-FR" }, + { 2066, "csEBCDICCAFR" }, + { 2067, "EBCDIC-DK-NO" }, + { 2067, "csEBCDICDKNO" }, + { 2068, "EBCDIC-DK-NO-A" }, + { 2068, "csEBCDICDKNOA" }, + { 2069, "EBCDIC-FI-SE" }, + { 2069, "csEBCDICFISE" }, + { 2070, "EBCDIC-FI-SE-A" }, + { 2070, "csEBCDICFISEA" }, + { 2071, "EBCDIC-FR" }, + { 2071, "csEBCDICFR" }, + { 2072, "EBCDIC-IT" }, + { 2072, "csEBCDICIT" }, + { 2073, "EBCDIC-PT" }, + { 2073, "csEBCDICPT" }, + { 2074, "EBCDIC-ES" }, + { 2074, "csEBCDICES" }, + { 2075, "EBCDIC-ES-A" }, + { 2075, "csEBCDICESA" }, + { 2076, "EBCDIC-ES-S" }, + { 2076, "csEBCDICESS" }, + { 2077, "EBCDIC-UK" }, + { 2077, "csEBCDICUK" }, + { 2078, "EBCDIC-US" }, + { 2078, "csEBCDICUS" }, + { 2079, "UNKNOWN-8BIT" }, + { 2079, "csUnknown8BiT" }, + { 2080, "MNEMONIC" }, + { 2080, "csMnemonic" }, + { 2081, "MNEM" }, + { 2081, "csMnem" }, + { 2082, "VISCII" }, + { 2082, "csVISCII" }, + { 2083, "VIQR" }, + { 2083, "csVIQR" }, + { 2084, "KOI8-R" }, + { 2084, "csKOI8R" }, + { 2085, "HZ-GB-2312" }, + { 2086, "IBM866" }, + { 2086, "cp866" }, + { 2086, "866" }, + { 2086, "csIBM866" }, + { 2087, "IBM775" }, + { 2087, "cp775" }, + { 2087, "csPC775Baltic" }, + { 2088, "KOI8-U" }, + { 2088, "csKOI8U" }, + { 2089, "IBM00858" }, + { 2089, "CCSID00858" }, + { 2089, "CP00858" }, + { 2089, "PC-Multilingual-850+euro" }, + { 2089, "csIBM00858" }, + { 2090, "IBM00924" }, + { 2090, "CCSID00924" }, + { 2090, "CP00924" }, + { 2090, "ebcdic-Latin9--euro" }, + { 2090, "csIBM00924" }, + { 2091, "IBM01140" }, + { 2091, "CCSID01140" }, + { 2091, "CP01140" }, + { 2091, "ebcdic-us-37+euro" }, + { 2091, "csIBM01140" }, + { 2092, "IBM01141" }, + { 2092, "CCSID01141" }, + { 2092, "CP01141" }, + { 2092, "ebcdic-de-273+euro" }, + { 2092, "csIBM01141" }, + { 2093, "IBM01142" }, + { 2093, "CCSID01142" }, + { 2093, "CP01142" }, + { 2093, "ebcdic-dk-277+euro" }, + { 2093, "ebcdic-no-277+euro" }, + { 2093, "csIBM01142" }, + { 2094, "IBM01143" }, + { 2094, "CCSID01143" }, + { 2094, "CP01143" }, + { 2094, "ebcdic-fi-278+euro" }, + { 2094, "ebcdic-se-278+euro" }, + { 2094, "csIBM01143" }, + { 2095, "IBM01144" }, + { 2095, "CCSID01144" }, + { 2095, "CP01144" }, + { 2095, "ebcdic-it-280+euro" }, + { 2095, "csIBM01144" }, + { 2096, "IBM01145" }, + { 2096, "CCSID01145" }, + { 2096, "CP01145" }, + { 2096, "ebcdic-es-284+euro" }, + { 2096, "csIBM01145" }, + { 2097, "IBM01146" }, + { 2097, "CCSID01146" }, + { 2097, "CP01146" }, + { 2097, "ebcdic-gb-285+euro" }, + { 2097, "csIBM01146" }, + { 2098, "IBM01147" }, + { 2098, "CCSID01147" }, + { 2098, "CP01147" }, + { 2098, "ebcdic-fr-297+euro" }, + { 2098, "csIBM01147" }, + { 2099, "IBM01148" }, + { 2099, "CCSID01148" }, + { 2099, "CP01148" }, + { 2099, "ebcdic-international-500+euro" }, + { 2099, "csIBM01148" }, + { 2100, "IBM01149" }, + { 2100, "CCSID01149" }, + { 2100, "CP01149" }, + { 2100, "ebcdic-is-871+euro" }, + { 2100, "csIBM01149" }, + { 2101, "Big5-HKSCS" }, + { 2101, "csBig5HKSCS" }, + { 2102, "IBM1047" }, + { 2102, "IBM-1047" }, + { 2102, "csIBM1047" }, + { 2103, "PTCP154" }, + { 2103, "csPTCP154" }, + { 2103, "PT154" }, + { 2103, "CP154" }, + { 2103, "Cyrillic-Asian" }, + { 2104, "Amiga-1251" }, + { 2104, "Ami1251" }, + { 2104, "Amiga1251" }, + { 2104, "Ami-1251" }, + { 2104, "csAmiga1251" }, + { 2104, "(Aliases" }, + { 2104, "are" }, + { 2104, "provided" }, + { 2104, "for" }, + { 2104, "historical" }, + { 2104, "reasons" }, + { 2104, "and" }, + { 2104, "should" }, + { 2104, "not" }, + { 2104, "be" }, + { 2104, "used)" }, + { 2104, "[Malyshev]" }, + { 2105, "KOI7-switched" }, + { 2105, "csKOI7switched" }, + { 2106, "BRF" }, + { 2106, "csBRF" }, + { 2107, "TSCII" }, + { 2107, "csTSCII" }, + { 2108, "CP51932" }, + { 2108, "csCP51932" }, + { 2109, "windows-874" }, + { 2109, "cswindows874" }, + { 2250, "windows-1250" }, + { 2250, "cswindows1250" }, + { 2251, "windows-1251" }, + { 2251, "cswindows1251" }, + { 2252, "windows-1252" }, + { 2252, "cswindows1252" }, + { 2253, "windows-1253" }, + { 2253, "cswindows1253" }, + { 2254, "windows-1254" }, + { 2254, "cswindows1254" }, + { 2255, "windows-1255" }, + { 2255, "cswindows1255" }, + { 2256, "windows-1256" }, + { 2256, "cswindows1256" }, + { 2257, "windows-1257" }, + { 2257, "cswindows1257" }, + { 2258, "windows-1258" }, + { 2258, "cswindows1258" }, + { 2259, "TIS-620" }, + { 2259, "csTIS620" }, + { 2259, "ISO-8859-11" }, + { 2260, "CP50220" }, + { 2260, "csCP50220" }, + +#undef _GLIBCXX_GET_ENCODING_DATA diff --git a/template/sysroot/include/bits/time_members.h b/template/sysroot/include/bits/time_members.h new file mode 100644 index 0000000..44a7ef9 --- /dev/null +++ b/template/sysroot/include/bits/time_members.h @@ -0,0 +1,92 @@ +// std::time_get, std::time_put implementation, generic version -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/time_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ + +// +// ISO C++ 14882: 22.2.5.1.2 - time_get functions +// ISO C++ 14882: 22.2.5.3.2 - time_put functions +// + +// Written by Benjamin Kosnik + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + __timepunct<_CharT>::__timepunct(size_t __refs) + : facet(__refs), _M_data(0) + { + _M_name_timepunct = _S_get_c_name(); + _M_initialize_timepunct(); + } + + template + __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs) + : facet(__refs), _M_data(__cache) + { + _M_name_timepunct = _S_get_c_name(); + _M_initialize_timepunct(); + } + + template + __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s, + size_t __refs) + : facet(__refs), _M_data(0) + { + if (__builtin_strcmp(__s, _S_get_c_name()) != 0) + { + const size_t __len = __builtin_strlen(__s) + 1; + char* __tmp = new char[__len]; + __builtin_memcpy(__tmp, __s, __len); + _M_name_timepunct = __tmp; + } + else + _M_name_timepunct = _S_get_c_name(); + + __try + { _M_initialize_timepunct(__cloc); } + __catch(...) + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + __throw_exception_again; + } + } + + template + __timepunct<_CharT>::~__timepunct() + { + if (_M_name_timepunct != _S_get_c_name()) + delete [] _M_name_timepunct; + delete _M_data; + _S_destroy_c_locale(_M_c_locale_timepunct); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/template/sysroot/include/bits/unicode-data.h b/template/sysroot/include/bits/unicode-data.h new file mode 100644 index 0000000..e39a6c4 --- /dev/null +++ b/template/sysroot/include/bits/unicode-data.h @@ -0,0 +1,476 @@ +// Generated by contrib/unicode/gen_libstdcxx_unicode_data.py, do not edit. + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unicode-data.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{format} + */ + +#ifndef _GLIBCXX_GET_UNICODE_DATA +# error "This is not a public header, do not include it directly" +#elif _GLIBCXX_GET_UNICODE_DATA != 150100 +# error "Version mismatch for Unicode static data" +#endif + + // Table generated by contrib/unicode/gen_std_format_width.py, + // from EastAsianWidth.txt from the Unicode standard. + inline constexpr char32_t __width_edges[] = { + 0x1100, 0x1160, 0x231a, 0x231c, 0x2329, 0x232b, 0x23e9, 0x23ed, + 0x23f0, 0x23f1, 0x23f3, 0x23f4, 0x25fd, 0x25ff, 0x2614, 0x2616, + 0x2648, 0x2654, 0x267f, 0x2680, 0x2693, 0x2694, 0x26a1, 0x26a2, + 0x26aa, 0x26ac, 0x26bd, 0x26bf, 0x26c4, 0x26c6, 0x26ce, 0x26cf, + 0x26d4, 0x26d5, 0x26ea, 0x26eb, 0x26f2, 0x26f4, 0x26f5, 0x26f6, + 0x26fa, 0x26fb, 0x26fd, 0x26fe, 0x2705, 0x2706, 0x270a, 0x270c, + 0x2728, 0x2729, 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756, + 0x2757, 0x2758, 0x2795, 0x2798, 0x27b0, 0x27b1, 0x27bf, 0x27c0, + 0x2b1b, 0x2b1d, 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x2e80, 0x2e9a, + 0x2e9b, 0x2ef4, 0x2f00, 0x2fd6, 0x2ff0, 0x303f, 0x3041, 0x3097, + 0x3099, 0x3100, 0x3105, 0x3130, 0x3131, 0x318f, 0x3190, 0x31e4, + 0x31ef, 0x321f, 0x3220, 0x3248, 0x3250, 0xa48d, 0xa490, 0xa4c7, + 0xa960, 0xa97d, 0xac00, 0xd7a4, 0xf900, 0xfb00, 0xfe10, 0xfe1a, + 0xfe30, 0xfe53, 0xfe54, 0xfe67, 0xfe68, 0xfe6c, 0xff01, 0xff61, + 0xffe0, 0xffe7, 0x16fe0, 0x16fe5, 0x16ff0, 0x16ff2, 0x17000, 0x187f8, + 0x18800, 0x18cd6, 0x18d00, 0x18d09, 0x1aff0, 0x1aff4, 0x1aff5, 0x1affc, + 0x1affd, 0x1afff, 0x1b000, 0x1b123, 0x1b132, 0x1b133, 0x1b150, 0x1b153, + 0x1b155, 0x1b156, 0x1b164, 0x1b168, 0x1b170, 0x1b2fc, 0x1f004, 0x1f005, + 0x1f0cf, 0x1f0d0, 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f200, 0x1f203, + 0x1f210, 0x1f23c, 0x1f240, 0x1f249, 0x1f250, 0x1f252, 0x1f260, 0x1f266, + 0x1f300, 0x1f650, 0x1f680, 0x1f6c6, 0x1f6cc, 0x1f6cd, 0x1f6d0, 0x1f6d3, + 0x1f6d5, 0x1f6d8, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd, + 0x1f7e0, 0x1f7ec, 0x1f7f0, 0x1f7f1, 0x1f900, 0x1fa00, 0x1fa70, 0x1fa7d, + 0x1fa80, 0x1fa89, 0x1fa90, 0x1fabe, 0x1fabf, 0x1fac6, 0x1face, 0x1fadc, + 0x1fae0, 0x1fae9, 0x1faf0, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe, + }; + + enum class _Gcb_property { + _Gcb_Other = 0, + _Gcb_Control = 1, + _Gcb_LF = 2, + _Gcb_CR = 3, + _Gcb_Extend = 4, + _Gcb_Prepend = 5, + _Gcb_SpacingMark = 6, + _Gcb_L = 7, + _Gcb_V = 8, + _Gcb_T = 9, + _Gcb_ZWJ = 10, + _Gcb_LV = 11, + _Gcb_LVT = 12, + _Gcb_Regional_Indicator = 13, + }; + + // Values generated by contrib/unicode/gen_std_format_width.py, + // from GraphemeBreakProperty.txt from the Unicode standard. + // Entries are (code_point << shift_bits) + property. + inline constexpr int __gcb_shift_bits = 0x4; + inline constexpr uint32_t __gcb_edges[] = { + 0x1, 0xa2, 0xb1, 0xd3, 0xe1, 0x200, + 0x7f1, 0xa00, 0xad1, 0xae0, 0x3004, 0x3700, + 0x4834, 0x48a0, 0x5914, 0x5be0, 0x5bf4, 0x5c00, + 0x5c14, 0x5c30, 0x5c44, 0x5c60, 0x5c74, 0x5c80, + 0x6005, 0x6060, 0x6104, 0x61b0, 0x61c1, 0x61d0, + 0x64b4, 0x6600, 0x6704, 0x6710, 0x6d64, 0x6dd5, + 0x6de0, 0x6df4, 0x6e50, 0x6e74, 0x6e90, 0x6ea4, + 0x6ee0, 0x70f5, 0x7100, 0x7114, 0x7120, 0x7304, + 0x74b0, 0x7a64, 0x7b10, 0x7eb4, 0x7f40, 0x7fd4, + 0x7fe0, 0x8164, 0x81a0, 0x81b4, 0x8240, 0x8254, + 0x8280, 0x8294, 0x82e0, 0x8594, 0x85c0, 0x8905, + 0x8920, 0x8984, 0x8a00, 0x8ca4, 0x8e25, 0x8e34, + 0x9036, 0x9040, 0x93a4, 0x93b6, 0x93c4, 0x93d0, + 0x93e6, 0x9414, 0x9496, 0x94d4, 0x94e6, 0x9500, + 0x9514, 0x9580, 0x9624, 0x9640, 0x9814, 0x9826, + 0x9840, 0x9bc4, 0x9bd0, 0x9be4, 0x9bf6, 0x9c14, + 0x9c50, 0x9c76, 0x9c90, 0x9cb6, 0x9cd4, 0x9ce0, + 0x9d74, 0x9d80, 0x9e24, 0x9e40, 0x9fe4, 0x9ff0, + 0xa014, 0xa036, 0xa040, 0xa3c4, 0xa3d0, 0xa3e6, + 0xa414, 0xa430, 0xa474, 0xa490, 0xa4b4, 0xa4e0, + 0xa514, 0xa520, 0xa704, 0xa720, 0xa754, 0xa760, + 0xa814, 0xa836, 0xa840, 0xabc4, 0xabd0, 0xabe6, + 0xac14, 0xac60, 0xac74, 0xac96, 0xaca0, 0xacb6, + 0xacd4, 0xace0, 0xae24, 0xae40, 0xafa4, 0xb000, + 0xb014, 0xb026, 0xb040, 0xb3c4, 0xb3d0, 0xb3e4, + 0xb406, 0xb414, 0xb450, 0xb476, 0xb490, 0xb4b6, + 0xb4d4, 0xb4e0, 0xb554, 0xb580, 0xb624, 0xb640, + 0xb824, 0xb830, 0xbbe4, 0xbbf6, 0xbc04, 0xbc16, + 0xbc30, 0xbc66, 0xbc90, 0xbca6, 0xbcd4, 0xbce0, + 0xbd74, 0xbd80, 0xc004, 0xc016, 0xc044, 0xc050, + 0xc3c4, 0xc3d0, 0xc3e4, 0xc416, 0xc450, 0xc464, + 0xc490, 0xc4a4, 0xc4e0, 0xc554, 0xc570, 0xc624, + 0xc640, 0xc814, 0xc826, 0xc840, 0xcbc4, 0xcbd0, + 0xcbe6, 0xcbf4, 0xcc06, 0xcc24, 0xcc36, 0xcc50, + 0xcc64, 0xcc76, 0xcc90, 0xcca6, 0xccc4, 0xcce0, + 0xcd54, 0xcd70, 0xce24, 0xce40, 0xcf36, 0xcf40, + 0xd004, 0xd026, 0xd040, 0xd3b4, 0xd3d0, 0xd3e4, + 0xd3f6, 0xd414, 0xd450, 0xd466, 0xd490, 0xd4a6, + 0xd4d4, 0xd4e5, 0xd4f0, 0xd574, 0xd580, 0xd624, + 0xd640, 0xd814, 0xd826, 0xd840, 0xdca4, 0xdcb0, + 0xdcf4, 0xdd06, 0xdd24, 0xdd50, 0xdd64, 0xdd70, + 0xdd86, 0xddf4, 0xde00, 0xdf26, 0xdf40, 0xe314, + 0xe320, 0xe336, 0xe344, 0xe3b0, 0xe474, 0xe4f0, + 0xeb14, 0xeb20, 0xeb36, 0xeb44, 0xebd0, 0xec84, + 0xecf0, 0xf184, 0xf1a0, 0xf354, 0xf360, 0xf374, + 0xf380, 0xf394, 0xf3a0, 0xf3e6, 0xf400, 0xf714, + 0xf7f6, 0xf804, 0xf850, 0xf864, 0xf880, 0xf8d4, + 0xf980, 0xf994, 0xfbd0, 0xfc64, 0xfc70, 0x102d4, + 0x10316, 0x10324, 0x10380, 0x10394, 0x103b6, 0x103d4, + 0x103f0, 0x10566, 0x10584, 0x105a0, 0x105e4, 0x10610, + 0x10714, 0x10750, 0x10824, 0x10830, 0x10846, 0x10854, + 0x10870, 0x108d4, 0x108e0, 0x109d4, 0x109e0, 0x11007, + 0x11608, 0x11a89, 0x12000, 0x135d4, 0x13600, 0x17124, + 0x17156, 0x17160, 0x17324, 0x17346, 0x17350, 0x17524, + 0x17540, 0x17724, 0x17740, 0x17b44, 0x17b66, 0x17b74, + 0x17be6, 0x17c64, 0x17c76, 0x17c94, 0x17d40, 0x17dd4, + 0x17de0, 0x180b4, 0x180e1, 0x180f4, 0x18100, 0x18854, + 0x18870, 0x18a94, 0x18aa0, 0x19204, 0x19236, 0x19274, + 0x19296, 0x192c0, 0x19306, 0x19324, 0x19336, 0x19394, + 0x193c0, 0x1a174, 0x1a196, 0x1a1b4, 0x1a1c0, 0x1a556, + 0x1a564, 0x1a576, 0x1a584, 0x1a5f0, 0x1a604, 0x1a610, + 0x1a624, 0x1a630, 0x1a654, 0x1a6d6, 0x1a734, 0x1a7d0, + 0x1a7f4, 0x1a800, 0x1ab04, 0x1acf0, 0x1b004, 0x1b046, + 0x1b050, 0x1b344, 0x1b3b6, 0x1b3c4, 0x1b3d6, 0x1b424, + 0x1b436, 0x1b450, 0x1b6b4, 0x1b740, 0x1b804, 0x1b826, + 0x1b830, 0x1ba16, 0x1ba24, 0x1ba66, 0x1ba84, 0x1baa6, + 0x1bab4, 0x1bae0, 0x1be64, 0x1be76, 0x1be84, 0x1bea6, + 0x1bed4, 0x1bee6, 0x1bef4, 0x1bf26, 0x1bf40, 0x1c246, + 0x1c2c4, 0x1c346, 0x1c364, 0x1c380, 0x1cd04, 0x1cd30, + 0x1cd44, 0x1ce16, 0x1ce24, 0x1ce90, 0x1ced4, 0x1cee0, + 0x1cf44, 0x1cf50, 0x1cf76, 0x1cf84, 0x1cfa0, 0x1dc04, + 0x1e000, 0x200b1, 0x200c4, 0x200da, 0x200e1, 0x20100, + 0x20281, 0x202f0, 0x20601, 0x20700, 0x20d04, 0x20f10, + 0x2cef4, 0x2cf20, 0x2d7f4, 0x2d800, 0x2de04, 0x2e000, + 0x302a4, 0x30300, 0x30994, 0x309b0, 0xa66f4, 0xa6730, + 0xa6744, 0xa67e0, 0xa69e4, 0xa6a00, 0xa6f04, 0xa6f20, + 0xa8024, 0xa8030, 0xa8064, 0xa8070, 0xa80b4, 0xa80c0, + 0xa8236, 0xa8254, 0xa8276, 0xa8280, 0xa82c4, 0xa82d0, + 0xa8806, 0xa8820, 0xa8b46, 0xa8c44, 0xa8c60, 0xa8e04, + 0xa8f20, 0xa8ff4, 0xa9000, 0xa9264, 0xa92e0, 0xa9474, + 0xa9526, 0xa9540, 0xa9607, 0xa97d0, 0xa9804, 0xa9836, + 0xa9840, 0xa9b34, 0xa9b46, 0xa9b64, 0xa9ba6, 0xa9bc4, + 0xa9be6, 0xa9c10, 0xa9e54, 0xa9e60, 0xaa294, 0xaa2f6, + 0xaa314, 0xaa336, 0xaa354, 0xaa370, 0xaa434, 0xaa440, + 0xaa4c4, 0xaa4d6, 0xaa4e0, 0xaa7c4, 0xaa7d0, 0xaab04, + 0xaab10, 0xaab24, 0xaab50, 0xaab74, 0xaab90, 0xaabe4, + 0xaac00, 0xaac14, 0xaac20, 0xaaeb6, 0xaaec4, 0xaaee6, + 0xaaf00, 0xaaf56, 0xaaf64, 0xaaf70, 0xabe36, 0xabe54, + 0xabe66, 0xabe84, 0xabe96, 0xabeb0, 0xabec6, 0xabed4, + 0xabee0, 0xac00b, 0xac01c, 0xac1cb, 0xac1dc, 0xac38b, + 0xac39c, 0xac54b, 0xac55c, 0xac70b, 0xac71c, 0xac8cb, + 0xac8dc, 0xaca8b, 0xaca9c, 0xacc4b, 0xacc5c, 0xace0b, + 0xace1c, 0xacfcb, 0xacfdc, 0xad18b, 0xad19c, 0xad34b, + 0xad35c, 0xad50b, 0xad51c, 0xad6cb, 0xad6dc, 0xad88b, + 0xad89c, 0xada4b, 0xada5c, 0xadc0b, 0xadc1c, 0xaddcb, + 0xadddc, 0xadf8b, 0xadf9c, 0xae14b, 0xae15c, 0xae30b, + 0xae31c, 0xae4cb, 0xae4dc, 0xae68b, 0xae69c, 0xae84b, + 0xae85c, 0xaea0b, 0xaea1c, 0xaebcb, 0xaebdc, 0xaed8b, + 0xaed9c, 0xaef4b, 0xaef5c, 0xaf10b, 0xaf11c, 0xaf2cb, + 0xaf2dc, 0xaf48b, 0xaf49c, 0xaf64b, 0xaf65c, 0xaf80b, + 0xaf81c, 0xaf9cb, 0xaf9dc, 0xafb8b, 0xafb9c, 0xafd4b, + 0xafd5c, 0xaff0b, 0xaff1c, 0xb00cb, 0xb00dc, 0xb028b, + 0xb029c, 0xb044b, 0xb045c, 0xb060b, 0xb061c, 0xb07cb, + 0xb07dc, 0xb098b, 0xb099c, 0xb0b4b, 0xb0b5c, 0xb0d0b, + 0xb0d1c, 0xb0ecb, 0xb0edc, 0xb108b, 0xb109c, 0xb124b, + 0xb125c, 0xb140b, 0xb141c, 0xb15cb, 0xb15dc, 0xb178b, + 0xb179c, 0xb194b, 0xb195c, 0xb1b0b, 0xb1b1c, 0xb1ccb, + 0xb1cdc, 0xb1e8b, 0xb1e9c, 0xb204b, 0xb205c, 0xb220b, + 0xb221c, 0xb23cb, 0xb23dc, 0xb258b, 0xb259c, 0xb274b, + 0xb275c, 0xb290b, 0xb291c, 0xb2acb, 0xb2adc, 0xb2c8b, + 0xb2c9c, 0xb2e4b, 0xb2e5c, 0xb300b, 0xb301c, 0xb31cb, + 0xb31dc, 0xb338b, 0xb339c, 0xb354b, 0xb355c, 0xb370b, + 0xb371c, 0xb38cb, 0xb38dc, 0xb3a8b, 0xb3a9c, 0xb3c4b, + 0xb3c5c, 0xb3e0b, 0xb3e1c, 0xb3fcb, 0xb3fdc, 0xb418b, + 0xb419c, 0xb434b, 0xb435c, 0xb450b, 0xb451c, 0xb46cb, + 0xb46dc, 0xb488b, 0xb489c, 0xb4a4b, 0xb4a5c, 0xb4c0b, + 0xb4c1c, 0xb4dcb, 0xb4ddc, 0xb4f8b, 0xb4f9c, 0xb514b, + 0xb515c, 0xb530b, 0xb531c, 0xb54cb, 0xb54dc, 0xb568b, + 0xb569c, 0xb584b, 0xb585c, 0xb5a0b, 0xb5a1c, 0xb5bcb, + 0xb5bdc, 0xb5d8b, 0xb5d9c, 0xb5f4b, 0xb5f5c, 0xb610b, + 0xb611c, 0xb62cb, 0xb62dc, 0xb648b, 0xb649c, 0xb664b, + 0xb665c, 0xb680b, 0xb681c, 0xb69cb, 0xb69dc, 0xb6b8b, + 0xb6b9c, 0xb6d4b, 0xb6d5c, 0xb6f0b, 0xb6f1c, 0xb70cb, + 0xb70dc, 0xb728b, 0xb729c, 0xb744b, 0xb745c, 0xb760b, + 0xb761c, 0xb77cb, 0xb77dc, 0xb798b, 0xb799c, 0xb7b4b, + 0xb7b5c, 0xb7d0b, 0xb7d1c, 0xb7ecb, 0xb7edc, 0xb808b, + 0xb809c, 0xb824b, 0xb825c, 0xb840b, 0xb841c, 0xb85cb, + 0xb85dc, 0xb878b, 0xb879c, 0xb894b, 0xb895c, 0xb8b0b, + 0xb8b1c, 0xb8ccb, 0xb8cdc, 0xb8e8b, 0xb8e9c, 0xb904b, + 0xb905c, 0xb920b, 0xb921c, 0xb93cb, 0xb93dc, 0xb958b, + 0xb959c, 0xb974b, 0xb975c, 0xb990b, 0xb991c, 0xb9acb, + 0xb9adc, 0xb9c8b, 0xb9c9c, 0xb9e4b, 0xb9e5c, 0xba00b, + 0xba01c, 0xba1cb, 0xba1dc, 0xba38b, 0xba39c, 0xba54b, + 0xba55c, 0xba70b, 0xba71c, 0xba8cb, 0xba8dc, 0xbaa8b, + 0xbaa9c, 0xbac4b, 0xbac5c, 0xbae0b, 0xbae1c, 0xbafcb, + 0xbafdc, 0xbb18b, 0xbb19c, 0xbb34b, 0xbb35c, 0xbb50b, + 0xbb51c, 0xbb6cb, 0xbb6dc, 0xbb88b, 0xbb89c, 0xbba4b, + 0xbba5c, 0xbbc0b, 0xbbc1c, 0xbbdcb, 0xbbddc, 0xbbf8b, + 0xbbf9c, 0xbc14b, 0xbc15c, 0xbc30b, 0xbc31c, 0xbc4cb, + 0xbc4dc, 0xbc68b, 0xbc69c, 0xbc84b, 0xbc85c, 0xbca0b, + 0xbca1c, 0xbcbcb, 0xbcbdc, 0xbcd8b, 0xbcd9c, 0xbcf4b, + 0xbcf5c, 0xbd10b, 0xbd11c, 0xbd2cb, 0xbd2dc, 0xbd48b, + 0xbd49c, 0xbd64b, 0xbd65c, 0xbd80b, 0xbd81c, 0xbd9cb, + 0xbd9dc, 0xbdb8b, 0xbdb9c, 0xbdd4b, 0xbdd5c, 0xbdf0b, + 0xbdf1c, 0xbe0cb, 0xbe0dc, 0xbe28b, 0xbe29c, 0xbe44b, + 0xbe45c, 0xbe60b, 0xbe61c, 0xbe7cb, 0xbe7dc, 0xbe98b, + 0xbe99c, 0xbeb4b, 0xbeb5c, 0xbed0b, 0xbed1c, 0xbeecb, + 0xbeedc, 0xbf08b, 0xbf09c, 0xbf24b, 0xbf25c, 0xbf40b, + 0xbf41c, 0xbf5cb, 0xbf5dc, 0xbf78b, 0xbf79c, 0xbf94b, + 0xbf95c, 0xbfb0b, 0xbfb1c, 0xbfccb, 0xbfcdc, 0xbfe8b, + 0xbfe9c, 0xc004b, 0xc005c, 0xc020b, 0xc021c, 0xc03cb, + 0xc03dc, 0xc058b, 0xc059c, 0xc074b, 0xc075c, 0xc090b, + 0xc091c, 0xc0acb, 0xc0adc, 0xc0c8b, 0xc0c9c, 0xc0e4b, + 0xc0e5c, 0xc100b, 0xc101c, 0xc11cb, 0xc11dc, 0xc138b, + 0xc139c, 0xc154b, 0xc155c, 0xc170b, 0xc171c, 0xc18cb, + 0xc18dc, 0xc1a8b, 0xc1a9c, 0xc1c4b, 0xc1c5c, 0xc1e0b, + 0xc1e1c, 0xc1fcb, 0xc1fdc, 0xc218b, 0xc219c, 0xc234b, + 0xc235c, 0xc250b, 0xc251c, 0xc26cb, 0xc26dc, 0xc288b, + 0xc289c, 0xc2a4b, 0xc2a5c, 0xc2c0b, 0xc2c1c, 0xc2dcb, + 0xc2ddc, 0xc2f8b, 0xc2f9c, 0xc314b, 0xc315c, 0xc330b, + 0xc331c, 0xc34cb, 0xc34dc, 0xc368b, 0xc369c, 0xc384b, + 0xc385c, 0xc3a0b, 0xc3a1c, 0xc3bcb, 0xc3bdc, 0xc3d8b, + 0xc3d9c, 0xc3f4b, 0xc3f5c, 0xc410b, 0xc411c, 0xc42cb, + 0xc42dc, 0xc448b, 0xc449c, 0xc464b, 0xc465c, 0xc480b, + 0xc481c, 0xc49cb, 0xc49dc, 0xc4b8b, 0xc4b9c, 0xc4d4b, + 0xc4d5c, 0xc4f0b, 0xc4f1c, 0xc50cb, 0xc50dc, 0xc528b, + 0xc529c, 0xc544b, 0xc545c, 0xc560b, 0xc561c, 0xc57cb, + 0xc57dc, 0xc598b, 0xc599c, 0xc5b4b, 0xc5b5c, 0xc5d0b, + 0xc5d1c, 0xc5ecb, 0xc5edc, 0xc608b, 0xc609c, 0xc624b, + 0xc625c, 0xc640b, 0xc641c, 0xc65cb, 0xc65dc, 0xc678b, + 0xc679c, 0xc694b, 0xc695c, 0xc6b0b, 0xc6b1c, 0xc6ccb, + 0xc6cdc, 0xc6e8b, 0xc6e9c, 0xc704b, 0xc705c, 0xc720b, + 0xc721c, 0xc73cb, 0xc73dc, 0xc758b, 0xc759c, 0xc774b, + 0xc775c, 0xc790b, 0xc791c, 0xc7acb, 0xc7adc, 0xc7c8b, + 0xc7c9c, 0xc7e4b, 0xc7e5c, 0xc800b, 0xc801c, 0xc81cb, + 0xc81dc, 0xc838b, 0xc839c, 0xc854b, 0xc855c, 0xc870b, + 0xc871c, 0xc88cb, 0xc88dc, 0xc8a8b, 0xc8a9c, 0xc8c4b, + 0xc8c5c, 0xc8e0b, 0xc8e1c, 0xc8fcb, 0xc8fdc, 0xc918b, + 0xc919c, 0xc934b, 0xc935c, 0xc950b, 0xc951c, 0xc96cb, + 0xc96dc, 0xc988b, 0xc989c, 0xc9a4b, 0xc9a5c, 0xc9c0b, + 0xc9c1c, 0xc9dcb, 0xc9ddc, 0xc9f8b, 0xc9f9c, 0xca14b, + 0xca15c, 0xca30b, 0xca31c, 0xca4cb, 0xca4dc, 0xca68b, + 0xca69c, 0xca84b, 0xca85c, 0xcaa0b, 0xcaa1c, 0xcabcb, + 0xcabdc, 0xcad8b, 0xcad9c, 0xcaf4b, 0xcaf5c, 0xcb10b, + 0xcb11c, 0xcb2cb, 0xcb2dc, 0xcb48b, 0xcb49c, 0xcb64b, + 0xcb65c, 0xcb80b, 0xcb81c, 0xcb9cb, 0xcb9dc, 0xcbb8b, + 0xcbb9c, 0xcbd4b, 0xcbd5c, 0xcbf0b, 0xcbf1c, 0xcc0cb, + 0xcc0dc, 0xcc28b, 0xcc29c, 0xcc44b, 0xcc45c, 0xcc60b, + 0xcc61c, 0xcc7cb, 0xcc7dc, 0xcc98b, 0xcc99c, 0xccb4b, + 0xccb5c, 0xccd0b, 0xccd1c, 0xccecb, 0xccedc, 0xcd08b, + 0xcd09c, 0xcd24b, 0xcd25c, 0xcd40b, 0xcd41c, 0xcd5cb, + 0xcd5dc, 0xcd78b, 0xcd79c, 0xcd94b, 0xcd95c, 0xcdb0b, + 0xcdb1c, 0xcdccb, 0xcdcdc, 0xcde8b, 0xcde9c, 0xce04b, + 0xce05c, 0xce20b, 0xce21c, 0xce3cb, 0xce3dc, 0xce58b, + 0xce59c, 0xce74b, 0xce75c, 0xce90b, 0xce91c, 0xceacb, + 0xceadc, 0xcec8b, 0xcec9c, 0xcee4b, 0xcee5c, 0xcf00b, + 0xcf01c, 0xcf1cb, 0xcf1dc, 0xcf38b, 0xcf39c, 0xcf54b, + 0xcf55c, 0xcf70b, 0xcf71c, 0xcf8cb, 0xcf8dc, 0xcfa8b, + 0xcfa9c, 0xcfc4b, 0xcfc5c, 0xcfe0b, 0xcfe1c, 0xcffcb, + 0xcffdc, 0xd018b, 0xd019c, 0xd034b, 0xd035c, 0xd050b, + 0xd051c, 0xd06cb, 0xd06dc, 0xd088b, 0xd089c, 0xd0a4b, + 0xd0a5c, 0xd0c0b, 0xd0c1c, 0xd0dcb, 0xd0ddc, 0xd0f8b, + 0xd0f9c, 0xd114b, 0xd115c, 0xd130b, 0xd131c, 0xd14cb, + 0xd14dc, 0xd168b, 0xd169c, 0xd184b, 0xd185c, 0xd1a0b, + 0xd1a1c, 0xd1bcb, 0xd1bdc, 0xd1d8b, 0xd1d9c, 0xd1f4b, + 0xd1f5c, 0xd210b, 0xd211c, 0xd22cb, 0xd22dc, 0xd248b, + 0xd249c, 0xd264b, 0xd265c, 0xd280b, 0xd281c, 0xd29cb, + 0xd29dc, 0xd2b8b, 0xd2b9c, 0xd2d4b, 0xd2d5c, 0xd2f0b, + 0xd2f1c, 0xd30cb, 0xd30dc, 0xd328b, 0xd329c, 0xd344b, + 0xd345c, 0xd360b, 0xd361c, 0xd37cb, 0xd37dc, 0xd398b, + 0xd399c, 0xd3b4b, 0xd3b5c, 0xd3d0b, 0xd3d1c, 0xd3ecb, + 0xd3edc, 0xd408b, 0xd409c, 0xd424b, 0xd425c, 0xd440b, + 0xd441c, 0xd45cb, 0xd45dc, 0xd478b, 0xd479c, 0xd494b, + 0xd495c, 0xd4b0b, 0xd4b1c, 0xd4ccb, 0xd4cdc, 0xd4e8b, + 0xd4e9c, 0xd504b, 0xd505c, 0xd520b, 0xd521c, 0xd53cb, + 0xd53dc, 0xd558b, 0xd559c, 0xd574b, 0xd575c, 0xd590b, + 0xd591c, 0xd5acb, 0xd5adc, 0xd5c8b, 0xd5c9c, 0xd5e4b, + 0xd5e5c, 0xd600b, 0xd601c, 0xd61cb, 0xd61dc, 0xd638b, + 0xd639c, 0xd654b, 0xd655c, 0xd670b, 0xd671c, 0xd68cb, + 0xd68dc, 0xd6a8b, 0xd6a9c, 0xd6c4b, 0xd6c5c, 0xd6e0b, + 0xd6e1c, 0xd6fcb, 0xd6fdc, 0xd718b, 0xd719c, 0xd734b, + 0xd735c, 0xd750b, 0xd751c, 0xd76cb, 0xd76dc, 0xd788b, + 0xd789c, 0xd7a40, 0xd7b08, 0xd7c70, 0xd7cb9, 0xd7fc0, + 0xfb1e4, 0xfb1f0, 0xfe004, 0xfe100, 0xfe204, 0xfe300, + 0xfeff1, 0xff000, 0xff9e4, 0xffa00, 0xfff01, 0xfffc0, + 0x101fd4, 0x101fe0, 0x102e04, 0x102e10, 0x103764, 0x1037b0, + 0x10a014, 0x10a040, 0x10a054, 0x10a070, 0x10a0c4, 0x10a100, + 0x10a384, 0x10a3b0, 0x10a3f4, 0x10a400, 0x10ae54, 0x10ae70, + 0x10d244, 0x10d280, 0x10eab4, 0x10ead0, 0x10efd4, 0x10f000, + 0x10f464, 0x10f510, 0x10f824, 0x10f860, 0x110006, 0x110014, + 0x110026, 0x110030, 0x110384, 0x110470, 0x110704, 0x110710, + 0x110734, 0x110750, 0x1107f4, 0x110826, 0x110830, 0x110b06, + 0x110b34, 0x110b76, 0x110b94, 0x110bb0, 0x110bd5, 0x110be0, + 0x110c24, 0x110c30, 0x110cd5, 0x110ce0, 0x111004, 0x111030, + 0x111274, 0x1112c6, 0x1112d4, 0x111350, 0x111456, 0x111470, + 0x111734, 0x111740, 0x111804, 0x111826, 0x111830, 0x111b36, + 0x111b64, 0x111bf6, 0x111c10, 0x111c25, 0x111c40, 0x111c94, + 0x111cd0, 0x111ce6, 0x111cf4, 0x111d00, 0x1122c6, 0x1122f4, + 0x112326, 0x112344, 0x112356, 0x112364, 0x112380, 0x1123e4, + 0x1123f0, 0x112414, 0x112420, 0x112df4, 0x112e06, 0x112e34, + 0x112eb0, 0x113004, 0x113026, 0x113040, 0x1133b4, 0x1133d0, + 0x1133e4, 0x1133f6, 0x113404, 0x113416, 0x113450, 0x113476, + 0x113490, 0x1134b6, 0x1134e0, 0x113574, 0x113580, 0x113626, + 0x113640, 0x113664, 0x1136d0, 0x113704, 0x113750, 0x114356, + 0x114384, 0x114406, 0x114424, 0x114456, 0x114464, 0x114470, + 0x1145e4, 0x1145f0, 0x114b04, 0x114b16, 0x114b34, 0x114b96, + 0x114ba4, 0x114bb6, 0x114bd4, 0x114be6, 0x114bf4, 0x114c16, + 0x114c24, 0x114c40, 0x115af4, 0x115b06, 0x115b24, 0x115b60, + 0x115b86, 0x115bc4, 0x115be6, 0x115bf4, 0x115c10, 0x115dc4, + 0x115de0, 0x116306, 0x116334, 0x1163b6, 0x1163d4, 0x1163e6, + 0x1163f4, 0x116410, 0x116ab4, 0x116ac6, 0x116ad4, 0x116ae6, + 0x116b04, 0x116b66, 0x116b74, 0x116b80, 0x1171d4, 0x117200, + 0x117224, 0x117266, 0x117274, 0x1172c0, 0x1182c6, 0x1182f4, + 0x118386, 0x118394, 0x1183b0, 0x119304, 0x119316, 0x119360, + 0x119376, 0x119390, 0x1193b4, 0x1193d6, 0x1193e4, 0x1193f5, + 0x119406, 0x119415, 0x119426, 0x119434, 0x119440, 0x119d16, + 0x119d44, 0x119d80, 0x119da4, 0x119dc6, 0x119e04, 0x119e10, + 0x119e46, 0x119e50, 0x11a014, 0x11a0b0, 0x11a334, 0x11a396, + 0x11a3a5, 0x11a3b4, 0x11a3f0, 0x11a474, 0x11a480, 0x11a514, + 0x11a576, 0x11a594, 0x11a5c0, 0x11a845, 0x11a8a4, 0x11a976, + 0x11a984, 0x11a9a0, 0x11c2f6, 0x11c304, 0x11c370, 0x11c384, + 0x11c3e6, 0x11c3f4, 0x11c400, 0x11c924, 0x11ca80, 0x11ca96, + 0x11caa4, 0x11cb16, 0x11cb24, 0x11cb46, 0x11cb54, 0x11cb70, + 0x11d314, 0x11d370, 0x11d3a4, 0x11d3b0, 0x11d3c4, 0x11d3e0, + 0x11d3f4, 0x11d465, 0x11d474, 0x11d480, 0x11d8a6, 0x11d8f0, + 0x11d904, 0x11d920, 0x11d936, 0x11d954, 0x11d966, 0x11d974, + 0x11d980, 0x11ef34, 0x11ef56, 0x11ef70, 0x11f004, 0x11f025, + 0x11f036, 0x11f040, 0x11f346, 0x11f364, 0x11f3b0, 0x11f3e6, + 0x11f404, 0x11f416, 0x11f424, 0x11f430, 0x134301, 0x134404, + 0x134410, 0x134474, 0x134560, 0x16af04, 0x16af50, 0x16b304, + 0x16b370, 0x16f4f4, 0x16f500, 0x16f516, 0x16f880, 0x16f8f4, + 0x16f930, 0x16fe44, 0x16fe50, 0x16ff06, 0x16ff20, 0x1bc9d4, + 0x1bc9f0, 0x1bca01, 0x1bca40, 0x1cf004, 0x1cf2e0, 0x1cf304, + 0x1cf470, 0x1d1654, 0x1d1666, 0x1d1674, 0x1d16a0, 0x1d16d6, + 0x1d16e4, 0x1d1731, 0x1d17b4, 0x1d1830, 0x1d1854, 0x1d18c0, + 0x1d1aa4, 0x1d1ae0, 0x1d2424, 0x1d2450, 0x1da004, 0x1da370, + 0x1da3b4, 0x1da6d0, 0x1da754, 0x1da760, 0x1da844, 0x1da850, + 0x1da9b4, 0x1daa00, 0x1daa14, 0x1dab00, 0x1e0004, 0x1e0070, + 0x1e0084, 0x1e0190, 0x1e01b4, 0x1e0220, 0x1e0234, 0x1e0250, + 0x1e0264, 0x1e02b0, 0x1e08f4, 0x1e0900, 0x1e1304, 0x1e1370, + 0x1e2ae4, 0x1e2af0, 0x1e2ec4, 0x1e2f00, 0x1e4ec4, 0x1e4f00, + 0x1e8d04, 0x1e8d70, 0x1e9444, 0x1e94b0, 0x1f1e6d, 0x1f2000, + 0x1f3fb4, 0x1f4000, 0xe00001, 0xe00204, 0xe00801, 0xe01004, + 0xe01f01, 0xe10000, + }; + + inline constexpr char32_t __incb_linkers[] = { + 0x094d, 0x09cd, 0x0acd, 0x0b4d, 0x0c4d, 0x0d4d, + }; + + enum class _InCB { _Consonant = 1, _Extend = 2 }; + + // Values generated by contrib/unicode/gen_std_format_width.py, + // from DerivedCoreProperties.txt from the Unicode standard. + // Entries are (code_point << 2) + property. + inline constexpr uint32_t __incb_edges[] = { + 0xc02, 0xd3c, 0xd42, 0xdc0, 0x120e, 0x1220, + 0x1646, 0x16f8, 0x16fe, 0x1700, 0x1706, 0x170c, + 0x1712, 0x1718, 0x171e, 0x1720, 0x1842, 0x186c, + 0x192e, 0x1980, 0x19c2, 0x19c4, 0x1b5a, 0x1b74, + 0x1b7e, 0x1b94, 0x1b9e, 0x1ba4, 0x1baa, 0x1bb8, + 0x1c46, 0x1c48, 0x1cc2, 0x1d2c, 0x1fae, 0x1fd0, + 0x1ff6, 0x1ff8, 0x205a, 0x2068, 0x206e, 0x2090, + 0x2096, 0x20a0, 0x20a6, 0x20b8, 0x2166, 0x2170, + 0x2262, 0x2280, 0x232a, 0x2388, 0x238e, 0x2400, + 0x2455, 0x24e8, 0x24f2, 0x24f4, 0x2546, 0x2554, + 0x2561, 0x2580, 0x25e1, 0x2600, 0x2655, 0x26a4, + 0x26a9, 0x26c4, 0x26c9, 0x26cc, 0x26d9, 0x26e8, + 0x26f2, 0x26f4, 0x2771, 0x2778, 0x277d, 0x2780, + 0x27c1, 0x27c8, 0x27fa, 0x27fc, 0x28f2, 0x28f4, + 0x2a55, 0x2aa4, 0x2aa9, 0x2ac4, 0x2ac9, 0x2ad0, + 0x2ad5, 0x2ae8, 0x2af2, 0x2af4, 0x2be5, 0x2be8, + 0x2c55, 0x2ca4, 0x2ca9, 0x2cc4, 0x2cc9, 0x2cd0, + 0x2cd5, 0x2ce8, 0x2cf2, 0x2cf4, 0x2d71, 0x2d78, + 0x2d7d, 0x2d80, 0x2dc5, 0x2dc8, 0x3055, 0x30a4, + 0x30a9, 0x30e8, 0x30f2, 0x30f4, 0x3156, 0x315c, + 0x3161, 0x316c, 0x32f2, 0x32f4, 0x3455, 0x34ee, + 0x34f4, 0x38e2, 0x38ec, 0x3922, 0x3930, 0x3ae2, + 0x3aec, 0x3b22, 0x3b30, 0x3c62, 0x3c68, 0x3cd6, + 0x3cd8, 0x3cde, 0x3ce0, 0x3ce6, 0x3ce8, 0x3dc6, + 0x3dcc, 0x3dd2, 0x3dd4, 0x3dea, 0x3df8, 0x3e02, + 0x3e04, 0x3e0a, 0x3e14, 0x3e1a, 0x3e20, 0x3f1a, + 0x3f1c, 0x40de, 0x40e0, 0x40e6, 0x40ec, 0x4236, + 0x4238, 0x4d76, 0x4d80, 0x5c52, 0x5c54, 0x5f4a, + 0x5f4c, 0x5f76, 0x5f78, 0x62a6, 0x62a8, 0x64e6, + 0x64f0, 0x685e, 0x6864, 0x6982, 0x6984, 0x69d6, + 0x69f4, 0x69fe, 0x6a00, 0x6ac2, 0x6af8, 0x6afe, + 0x6b3c, 0x6cd2, 0x6cd4, 0x6dae, 0x6dd0, 0x6eae, + 0x6eb0, 0x6f9a, 0x6f9c, 0x70de, 0x70e0, 0x7342, + 0x734c, 0x7352, 0x7384, 0x738a, 0x73a4, 0x73b6, + 0x73b8, 0x73d2, 0x73d4, 0x73e2, 0x73e8, 0x7702, + 0x7800, 0x8036, 0x8038, 0x8342, 0x8374, 0x8386, + 0x8388, 0x8396, 0x83c4, 0xb3be, 0xb3c8, 0xb5fe, + 0xb600, 0xb782, 0xb800, 0xc0aa, 0xc0c0, 0xc266, + 0xc26c, 0x299be, 0x299c0, 0x299d2, 0x299f8, 0x29a7a, + 0x29a80, 0x29bc2, 0x29bc8, 0x2a0b2, 0x2a0b4, 0x2a382, + 0x2a3c8, 0x2a4ae, 0x2a4b8, 0x2a6ce, 0x2a6d0, 0x2aac2, + 0x2aac4, 0x2aaca, 0x2aad4, 0x2aade, 0x2aae4, 0x2aafa, + 0x2ab00, 0x2ab06, 0x2ab08, 0x2abda, 0x2abdc, 0x2afb6, + 0x2afb8, 0x3ec7a, 0x3ec7c, 0x3f882, 0x3f8c0, 0x407f6, + 0x407f8, 0x40b82, 0x40b84, 0x40dda, 0x40dec, 0x42836, + 0x42838, 0x4283e, 0x42840, 0x428e2, 0x428ec, 0x428fe, + 0x42900, 0x42b96, 0x42b9c, 0x43492, 0x434a0, 0x43aae, + 0x43ab4, 0x43bf6, 0x43c00, 0x43d1a, 0x43d44, 0x43e0a, + 0x43e18, 0x441c2, 0x441c4, 0x441fe, 0x44200, 0x442ea, + 0x442ec, 0x44402, 0x4440c, 0x444ce, 0x444d4, 0x445ce, + 0x445d0, 0x4472a, 0x4472c, 0x448da, 0x448dc, 0x44ba6, + 0x44bac, 0x44cee, 0x44cf4, 0x44d9a, 0x44db4, 0x44dc2, + 0x44dd4, 0x4511a, 0x4511c, 0x4517a, 0x4517c, 0x4530e, + 0x45310, 0x45702, 0x45704, 0x45ade, 0x45ae0, 0x45cae, + 0x45cb0, 0x460ea, 0x460ec, 0x464fa, 0x464fc, 0x4650e, + 0x46510, 0x468d2, 0x468d4, 0x4691e, 0x46920, 0x46a66, + 0x46a68, 0x4750a, 0x4750c, 0x47512, 0x47518, 0x4765e, + 0x47660, 0x47d0a, 0x47d0c, 0x5abc2, 0x5abd4, 0x5acc2, + 0x5acdc, 0x6f27a, 0x6f27c, 0x74596, 0x74598, 0x7459e, + 0x745a8, 0x745ba, 0x745cc, 0x745ee, 0x7460c, 0x74616, + 0x74630, 0x746aa, 0x746b8, 0x7490a, 0x74914, 0x78002, + 0x7801c, 0x78022, 0x78064, 0x7806e, 0x78088, 0x7808e, + 0x78094, 0x7809a, 0x780ac, 0x7823e, 0x78240, 0x784c2, + 0x784dc, 0x78aba, 0x78abc, 0x78bb2, 0x78bc0, 0x793b2, + 0x793c0, 0x7a342, 0x7a35c, 0x7a512, 0x7a52c, + }; + + // Table generated by contrib/unicode/gen_std_format_width.py, + // from emoji-data.txt from the Unicode standard. + inline constexpr char32_t __xpicto_edges[] = { + 0xa9, 0xaa, 0xae, 0xaf, 0x203c, 0x203d, 0x2049, 0x204a, + 0x2122, 0x2123, 0x2139, 0x213a, 0x2194, 0x219a, 0x21a9, 0x21ab, + 0x231a, 0x231c, 0x2328, 0x2329, 0x2388, 0x2389, 0x23cf, 0x23d0, + 0x23e9, 0x23f4, 0x23f8, 0x23fb, 0x24c2, 0x24c3, 0x25aa, 0x25ac, + 0x25b6, 0x25b7, 0x25c0, 0x25c1, 0x25fb, 0x25ff, 0x2600, 0x2606, + 0x2607, 0x2613, 0x2614, 0x2686, 0x2690, 0x2706, 0x2708, 0x2713, + 0x2714, 0x2715, 0x2716, 0x2717, 0x271d, 0x271e, 0x2721, 0x2722, + 0x2728, 0x2729, 0x2733, 0x2735, 0x2744, 0x2745, 0x2747, 0x2748, + 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756, 0x2757, 0x2758, + 0x2763, 0x2768, 0x2795, 0x2798, 0x27a1, 0x27a2, 0x27b0, 0x27b1, + 0x27bf, 0x27c0, 0x2934, 0x2936, 0x2b05, 0x2b08, 0x2b1b, 0x2b1d, + 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x3030, 0x3031, 0x303d, 0x303e, + 0x3297, 0x3298, 0x3299, 0x329a, 0x1f000, 0x1f100, 0x1f10d, 0x1f110, + 0x1f12f, 0x1f130, 0x1f16c, 0x1f172, 0x1f17e, 0x1f180, 0x1f18e, 0x1f18f, + 0x1f191, 0x1f19b, 0x1f1ad, 0x1f1e6, 0x1f201, 0x1f210, 0x1f21a, 0x1f21b, + 0x1f22f, 0x1f230, 0x1f232, 0x1f23b, 0x1f23c, 0x1f240, 0x1f249, 0x1f3fb, + 0x1f400, 0x1f53e, 0x1f546, 0x1f650, 0x1f680, 0x1f700, 0x1f774, 0x1f780, + 0x1f7d5, 0x1f800, 0x1f80c, 0x1f810, 0x1f848, 0x1f850, 0x1f85a, 0x1f860, + 0x1f888, 0x1f890, 0x1f8ae, 0x1f900, 0x1f90c, 0x1f93b, 0x1f93c, 0x1f946, + 0x1f947, 0x1fb00, 0x1fc00, 0x1fffe, + }; + +#undef _GLIBCXX_GET_UNICODE_DATA diff --git a/template/sysroot/include/bits/unicode.h b/template/sysroot/include/bits/unicode.h new file mode 100644 index 0000000..a14a17c --- /dev/null +++ b/template/sysroot/include/bits/unicode.h @@ -0,0 +1,1132 @@ +// Unicode utilities -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/unicode.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{format} + */ + +#ifndef _GLIBCXX_UNICODE_H +#define _GLIBCXX_UNICODE_H 1 + +#if __cplusplus >= 202002L +#include +#include // bit_width +#include // __detail::__from_chars_alnum_to_val_table +#include +#include +#include +#include +#include // iterator_t, sentinel_t, input_range, etc. +#include // view_interface + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace __unicode +{ + // A Unicode code point that is not a high or low surrogate. + constexpr bool + __is_scalar_value(char32_t __c) + { + if (__c < 0xD800) [[likely]] + return true; + return 0xDFFF < __c && __c <= 0x10FFFF; + } + + // A code point that can be encoded in a single code unit of type _CharT. + template + constexpr bool + __is_single_code_unit(char32_t __c) + { + if constexpr (__gnu_cxx::__int_traits<_CharT>::__max <= 0xFF) + return __c < 0x7F; // ASCII character + else + return __c < __gnu_cxx::__int_traits<_CharT>::__max + && __is_scalar_value(__c); + } + + // Based on https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2728r6.html#add-the-transcoding-iterator-template + + struct _Repl + { + constexpr char32_t + operator()() const noexcept + { return 0xFFFD; } + }; + + struct _Null_sentinel_t + { + template + requires default_initializable> + && equality_comparable_with, iter_value_t<_It>> + friend constexpr auto + operator==(_It __it, _Null_sentinel_t) + { return *__it == iter_value_t<_It>{}; } + }; + + template _Sent = _Iter, + typename _ErrorHandler = _Repl> + requires convertible_to, _FromFmt> + class _Utf_iterator + { + static_assert(forward_iterator<_Iter> || noexcept(_ErrorHandler()())); + + public: + using value_type = _ToFmt; + using difference_type = iter_difference_t<_Iter>; + using reference = value_type; + using iterator_concept + = std::__detail::__clamp_iter_cat<__iter_category_t<_Iter>, + bidirectional_iterator_tag>; + + constexpr _Utf_iterator() = default; + + constexpr + _Utf_iterator(_Iter __first, _Iter __it, _Sent __last) + requires bidirectional_iterator<_Iter> + : _M_first_and_curr{__first, __it}, _M_last(__last) + { + if (_M_curr() != _M_last) + _M_read(); + else + _M_buf = {}; + } + + constexpr + _Utf_iterator(_Iter __it, _Sent __last) + requires (!bidirectional_iterator<_Iter>) + : _M_first_and_curr{__it}, _M_last(__last) + { + if (_M_curr() != _M_last) + _M_read(); + else + _M_buf = {}; + } + + template + requires convertible_to<_Iter2, _Iter> && convertible_to<_Sent2, _Sent> + constexpr + _Utf_iterator(const _Utf_iterator<_FromFmt, _ToFmt, _Iter2, _Sent2, + _ErrorHandler>& __other) + : _M_buf(__other._M_buf), _M_first_and_curr(__other._M_first_and_curr), + _M_buf_index(__other._M_buf_index), _M_buf_last(__other._M_buf_last), + _M_last(__other._M_last) + { } + + [[nodiscard]] + constexpr _Iter + begin() const requires bidirectional_iterator<_Iter> + { return _M_first(); } + + [[nodiscard]] + constexpr _Sent + end() const { return _M_last; } + + [[nodiscard]] + constexpr _Iter + base() const requires forward_iterator<_Iter> + { return _M_curr(); } + + [[nodiscard]] + constexpr value_type + operator*() const { return _M_buf[_M_buf_index]; } + + constexpr _Utf_iterator& + operator++() + { + if (_M_buf_index + 1 == _M_buf_last && _M_curr() != _M_last) + { + if constexpr (forward_iterator<_Iter>) + std::advance(_M_curr(), _M_to_increment); + if (_M_curr() == _M_last) + _M_buf_index = 0; + else + _M_read(); + } + else if (_M_buf_index + 1 < _M_buf_last) + ++_M_buf_index; + return *this; + } + + constexpr _Utf_iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Utf_iterator& + operator--() requires bidirectional_iterator<_Iter> + { + if (!_M_buf_index && _M_curr() != _M_first()) + _M_read_reverse(); + else if (_M_buf_index) + --_M_buf_index; + return *this; + } + + constexpr _Utf_iterator + operator--(int) + { + auto __tmp = *this; + --*this; + return __tmp; + } + + [[nodiscard]] + friend constexpr bool + operator==(_Utf_iterator __lhs, _Utf_iterator __rhs) + requires forward_iterator<_Iter> || requires (_Iter __i) { __i != __i; } + { + if constexpr (forward_iterator<_Iter>) + return __lhs._M_curr() == __rhs._M_curr() + && __lhs._M_buf_index == __rhs._M_buf_index; + else if (__lhs._M_curr() != __rhs._M_curr()) + return false; + else if (__lhs._M_buf_index == __rhs._M_buf_index + && __lhs._M_buf_last == __rhs._M_buf_last) + return true; + else + return __lhs._M_buf_index == __lhs._M_buf_last + && __rhs._M_buf_index == __rhs._M_buf_last; + } + + [[nodiscard]] + friend constexpr bool + operator==(_Utf_iterator __lhs, _Sent __rhs) + { + if constexpr (forward_iterator<_Iter>) + return __lhs._M_curr() == __rhs; + else + return __lhs._M_curr() == __rhs + && __lhs._M_buf_index == __lhs._M_buf_last; + } + + private: + constexpr void + _M_read() + { + if constexpr (sizeof(_FromFmt) == sizeof(uint8_t)) + _M_read_utf8(); + else if constexpr (sizeof(_FromFmt) == sizeof(uint16_t)) + _M_read_utf16(); + else + { + static_assert(sizeof(_FromFmt) == sizeof(uint32_t)); + _M_read_utf32(); + } + } + + constexpr void + _M_read_reverse(); // TODO + + template + struct _Guard + { + _Guard(void*, _Iter&) { } + }; + + template requires forward_iterator<_It> + struct _Guard<_It> + { + constexpr ~_Guard() { _M_this->_M_curr() = std::move(_M_orig); } + _Utf_iterator* _M_this; + _It _M_orig; + }; + + constexpr void + _M_read_utf8() + { + _Guard<_Iter> __g{this, _M_curr()}; + char32_t __c{}; + const uint8_t __lo_bound = 0x80, __hi_bound = 0xBF; + uint8_t __u = *_M_curr()++; + uint8_t __to_incr = 1; + auto __incr = [&, this] { + ++__to_incr; + return ++_M_curr(); + }; + + if (__u <= 0x7F) [[likely]] // 0x00 to 0x7F + __c = __u; + else if (__u < 0xC2) [[unlikely]] + __c = _S_error(); + else if (_M_curr() == _M_last) [[unlikely]] + __c = _S_error(); + else if (__u <= 0xDF) // 0xC2 to 0xDF + { + __c = __u & 0x1F; + __u = *_M_curr(); + + if (__u < __lo_bound || __u > __hi_bound) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __incr(); + } + } + else if (__u <= 0xEF) // 0xE0 to 0xEF + { + const uint8_t __lo_bound_2 = __u == 0xE0 ? 0xA0 : __lo_bound; + const uint8_t __hi_bound_2 = __u == 0xED ? 0x9F : __hi_bound; + + __c = __u & 0x0F; + __u = *_M_curr(); + + if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]] + __c = _S_error(); + else if (__incr() == _M_last) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __u = *_M_curr(); + + if (__u < __lo_bound || __u > __hi_bound) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __incr(); + } + } + } + else if (__u <= 0xF4) // 0xF0 to 0xF4 + { + const uint8_t __lo_bound_2 = __u == 0xF0 ? 0x90 : __lo_bound; + const uint8_t __hi_bound_2 = __u == 0xF4 ? 0x8F : __hi_bound; + + __c = __u & 0x07; + __u = *_M_curr(); + + if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]] + __c = _S_error(); + else if (__incr() == _M_last) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __u = *_M_curr(); + + if (__u < __lo_bound || __u > __hi_bound) [[unlikely]] + __c = _S_error(); + else if (__incr() == _M_last) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __u = *_M_curr(); + + if (__u < __lo_bound || __u > __hi_bound) [[unlikely]] + __c = _S_error(); + else + { + __c = (__c << 6) | (__u & 0x3F); + __incr(); + } + } + } + } + else [[unlikely]] + __c = _S_error(); + + _M_update(__c, __to_incr); + } + + constexpr void + _M_read_utf16() + { + _Guard<_Iter> __g{this, _M_curr()}; + char32_t __c{}; + uint16_t __u = *_M_curr()++; + uint8_t __to_incr = 1; + + if (__u < 0xD800 || __u > 0xDFFF) [[likely]] + __c = __u; + else if (__u < 0xDC00 && _M_curr() != _M_last) + { + uint16_t __u2 = *_M_curr(); + if (__u2 < 0xDC00 || __u2 > 0xDFFF) [[unlikely]] + __c = _S_error(); + else + { + ++_M_curr(); + __to_incr = 2; + uint32_t __x = (__u & 0x3F) << 10 | __u2 & 0x3FF; + uint32_t __w = (__u >> 6) & 0x1F; + __c = (__w + 1) << 16 | __x; + } + } + else + __c = _S_error(); + + _M_update(__c, __to_incr); + } + + constexpr void + _M_read_utf32() + { + _Guard<_Iter> __g{this, _M_curr()}; + char32_t __c = *_M_curr()++; + if (!__is_scalar_value(__c)) [[unlikely]] + __c = _S_error(); + _M_update(__c, 1); + } + + // Encode the code point __c as one or more code units in _M_buf. + constexpr void + _M_update(char32_t __c, uint8_t __to_incr) + { + _M_to_increment = __to_incr; + _M_buf_index = 0; + if constexpr (sizeof(_ToFmt) == sizeof(uint32_t)) + { + _M_buf[0] = __c; + _M_buf_last = 1; + } + else if constexpr (sizeof(_ToFmt) == sizeof(uint16_t)) + { + if (__is_single_code_unit<_ToFmt>(__c)) + { + _M_buf[0] = __c; + _M_buf[1] = 0; + _M_buf_last = 1; + } + else + { + // From http://www.unicode.org/faq/utf_bom.html#utf16-4 + const char32_t __lead_offset = 0xD800 - (0x10000 >> 10); + char16_t __lead = __lead_offset + (__c >> 10); + char16_t __trail = 0xDC00 + (__c & 0x3FF); + _M_buf[0] = __lead; + _M_buf[1] = __trail; + _M_buf_last = 2; + } + } + else + { + static_assert(sizeof(_ToFmt) == 1); + int __bits = std::bit_width((uint32_t)__c); + if (__bits <= 7) [[likely]] + { + _M_buf[0] = __c; + _M_buf[1] = _M_buf[2] = _M_buf[3] = 0; + _M_buf_last = 1; + } + else if (__bits <= 11) + { + _M_buf[0] = 0xC0 | (__c >> 6); + _M_buf[1] = 0x80 | (__c & 0x3F); + _M_buf[2] = _M_buf[3] = 0; + _M_buf_last = 2; + } + else if (__bits <= 16) + { + _M_buf[0] = 0xE0 | (__c >> 12); + _M_buf[1] = 0x80 | ((__c >> 6) & 0x3F); + _M_buf[2] = 0x80 | (__c & 0x3F); + _M_buf[3] = 0; + _M_buf_last = 3; + } + else + { + _M_buf[0] = 0xF0 | ((__c >> 18) & 0x07); + _M_buf[1] = 0x80 | ((__c >> 12) & 0x3F); + _M_buf[2] = 0x80 | ((__c >> 6) & 0x3F); + _M_buf[3] = 0x80 | (__c & 0x3F); + _M_buf_last = 4; + } + } + } + + constexpr char32_t + _S_error() + { + char32_t __c = _ErrorHandler()(); + __glibcxx_assert(__is_scalar_value(__c)); + return __c; + } + + constexpr _Iter + _M_first() const requires bidirectional_iterator<_Iter> + { return _M_first_and_curr._M_first; } + + constexpr _Iter& + _M_curr() { return _M_first_and_curr._M_curr; } + + constexpr _Iter + _M_curr() const { return _M_first_and_curr._M_curr; } + + array _M_buf; + + template + struct _First_and_curr + { + _First_and_curr() = default; + + constexpr + _First_and_curr(_It __curr) : _M_curr(__curr) { } + + template _It2> + constexpr + _First_and_curr(const _First_and_curr<_It2>& __other) + : _M_curr(__other._M_curr) { } + + _It _M_curr; + }; + + template requires bidirectional_iterator<_It> + struct _First_and_curr<_It> + { + _First_and_curr() = default; + + constexpr + _First_and_curr(_It __first, _It __curr) + : _M_first(__first), _M_curr(__curr) { } + + template _It2> + constexpr + _First_and_curr(const _First_and_curr<_It2>& __other) + : _M_first(__other._M_first), _M_curr(__other._M_curr) { } + + _It _M_first; + _It _M_curr; + }; + + _First_and_curr<_Iter> _M_first_and_curr; + + uint8_t _M_buf_index = 0; + uint8_t _M_buf_last = 0; + uint8_t _M_to_increment = 0; + + [[no_unique_address]] _Sent _M_last; + + template _Sent2, + typename _ErrHandler> + requires convertible_to, _FromFmt2> + friend class _Utf_iterator; + }; + + template + class _Utf_view + : public ranges::view_interface<_Utf_view<_ToFormat, _Range>> + { + using _Iterator = _Utf_iterator, + _ToFormat, ranges::iterator_t<_Range>, + ranges::sentinel_t<_Range>>; + + template + constexpr auto + _M_begin(_Iter __first, _Sent __last) + { + if constexpr (bidirectional_iterator<_Iter>) + return _Iterator(__first, __first, __last); + else + return _Iterator(__first, __last); + } + + template + constexpr auto + _M_end(_Iter __first, _Sent __last) + { + if constexpr (!is_same_v<_Iter, _Sent>) + return __last; + else if constexpr (bidirectional_iterator<_Iter>) + return _Iterator(__first, __last, __last); + else + return _Iterator(__last, __last); + } + + _Range _M_base; + + public: + constexpr explicit + _Utf_view(_Range&& __r) : _M_base(std::forward<_Range>(__r)) { } + + constexpr auto begin() + { return _M_begin(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto end() + { return _M_end(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr bool empty() const { return ranges::empty(_M_base); } + }; + +#ifdef __cpp_char8_t + template + using _Utf8_view = _Utf_view; +#else + template + using _Utf8_view = _Utf_view; +#endif + template + using _Utf16_view = _Utf_view; + template + using _Utf32_view = _Utf_view; + +inline namespace __v15_1_0 +{ +#define _GLIBCXX_GET_UNICODE_DATA 150100 +#include "unicode-data.h" +#ifdef _GLIBCXX_GET_UNICODE_DATA +# error "Invalid unicode data" +#endif + + // The field width of a code point. + constexpr int + __field_width(char32_t __c) noexcept + { + if (__c < __width_edges[0]) [[likely]] + return 1; + + auto* __p = std::upper_bound(__width_edges, std::end(__width_edges), __c); + return (__p - __width_edges) % 2 + 1; + } + + // @pre c <= 0x10FFFF + constexpr _Gcb_property + __grapheme_cluster_break_property(char32_t __c) noexcept + { + constexpr uint32_t __mask = (1 << __gcb_shift_bits) - 1; + auto* __end = std::end(__gcb_edges); + auto* __p = std::lower_bound(__gcb_edges, __end, + (__c << __gcb_shift_bits) | __mask); + return _Gcb_property(__p[-1] & __mask); + } + + constexpr bool + __is_incb_linker(char32_t __c) noexcept + { + const auto __end = std::end(__incb_linkers); + // Array is small enough that linear search is faster than binary search. + return std::find(__incb_linkers, __end, __c) != __end; + } + + // @pre c <= 0x10FFFF + constexpr _InCB + __incb_property(char32_t __c) noexcept + { + if ((__c << 2) < __incb_edges[0]) [[likely]] + return _InCB(0); + + constexpr uint32_t __mask = 0x3; + auto* __end = std::end(__incb_edges); + auto* __p = std::lower_bound(__incb_edges, __end, (__c << 2) | __mask); + return _InCB(__p[-1] & __mask); + } + + constexpr bool + __is_extended_pictographic(char32_t __c) + { + if (__c < __xpicto_edges[0]) [[likely]] + return 0; + + auto* __p = std::upper_bound(__xpicto_edges, std::end(__xpicto_edges), __c); + return (__p - __xpicto_edges) % 2; + } + + struct _Grapheme_cluster_iterator_base + { + char32_t _M_c; // First code point in the cluster. + _Gcb_property _M_prop; // GCB property of _M_c. + enum class _XPicto : unsigned char { _Init, _Zwj, _Matched, _Failed }; + _XPicto _M_xpicto_seq_state = _XPicto::_Init; + unsigned char _M_RI_count = 0; + bool _M_incb_linker_seen = false; + + constexpr void + _M_reset(char32_t __c, _Gcb_property __p) + { + _M_c = __c; + _M_prop = __p; + _M_xpicto_seq_state = _XPicto::_Init; + _M_RI_count = 0; + _M_incb_linker_seen = false; + } + + constexpr void + _M_update_xpicto_seq_state(char32_t __c, _Gcb_property __p) + { + if (_M_xpicto_seq_state == _XPicto::_Failed) + return; + + auto __next_state = _XPicto::_Failed; + if (_M_xpicto_seq_state != _XPicto::_Zwj) // i.e. Init or Matched + { + if (__p == _Gcb_property::_Gcb_ZWJ) + { + if (_M_xpicto_seq_state == _XPicto::_Matched) + __next_state = _XPicto::_Zwj; + // We check _M_c here so that we do the lookup at most once, + // and only for clusters containing at least one ZWJ. + else if (__is_extended_pictographic(_M_c)) + __next_state = _XPicto::_Zwj; + } + else if (__p == _Gcb_property::_Gcb_Extend) + __next_state = _M_xpicto_seq_state; // no change + } + else // Zwj + { + // This assumes that all \p{Extended_Pictographic} emoji have + // Grapheme_Cluster_Break=Other. + if (__p == _Gcb_property::_Gcb_Other + && __is_extended_pictographic(__c)) + __next_state = _XPicto::_Matched; + } + _M_xpicto_seq_state = __next_state; + } + + constexpr void + _M_update_ri_count(_Gcb_property __p) + { + if (__p == _Gcb_property::_Gcb_Regional_Indicator) + ++_M_RI_count; + else + _M_RI_count = 0; + } + + constexpr void + _M_update_incb_state(char32_t __c, _Gcb_property) + { + if (__is_incb_linker(__c)) + _M_incb_linker_seen = true; + } + }; + + // Split a range into extended grapheme clusters. + template requires ranges::view<_View> + class _Grapheme_cluster_view + : public ranges::view_interface<_Grapheme_cluster_view<_View>> + { + public: + + constexpr + _Grapheme_cluster_view(_View __v) + : _M_begin(_Utf32_view<_View>(std::move(__v)).begin()) + { } + + constexpr auto begin() const { return _M_begin; } + constexpr auto end() const { return _M_begin.end(); } + + private: + struct _Iterator : private _Grapheme_cluster_iterator_base + { + private: + // Iterator over the underlying code points. + using _U32_iterator = ranges::iterator_t<_Utf32_view<_View>>; + + public: + // TODO: Change value_type to be subrange<_U32_iterator> instead? + // Alternatively, value_type could be _Utf32_view>. + // That would be the whole cluster, not just the first code point. + // Would need to store two iterators and find end of current cluster + // on increment, so operator* returns value_type(_M_base, _M_next). + using value_type = char32_t; + using iterator_concept = forward_iterator_tag; + using difference_type = ptrdiff_t; + + constexpr + _Iterator(_U32_iterator __i) + : _M_base(__i) + { + if (__i != __i.end()) + { + _M_c = *__i; + _M_prop = __grapheme_cluster_break_property(_M_c); + } + } + + // The first code point of the current extended grapheme cluster. + constexpr value_type + operator*() const + { return _M_c; } + + constexpr auto + operator->() const + { return &_M_c; } + + // Move to the next extended grapheme cluster. + constexpr _Iterator& + operator++() + { + const auto __end = _M_base.end(); + if (_M_base != __end) + { + auto __p_prev = _M_prop; + auto __it = _M_base; + while (++__it != __end) + { + char32_t __c = *__it; + auto __p = __grapheme_cluster_break_property(*__it); + _M_update_xpicto_seq_state(__c, __p); + _M_update_ri_count(__p); + _M_update_incb_state(__c, __p); + if (_M_is_break(__p_prev, __p, __it)) + { + // Found a grapheme cluster break + _M_reset(__c, __p); + break; + } + __p_prev = __p; + } + _M_base = __it; + } + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr bool + operator==(const _Iterator& __i) const + { return _M_base == __i._M_base; } + + // This supports iter != iter.end() + constexpr bool + operator==(const ranges::sentinel_t<_View>& __i) const + { return _M_base == __i; } + + // Iterator to the start of the current cluster. + constexpr auto base() const { return _M_base.base(); } + + // The end of the underlying view (not the end of the current cluster!) + constexpr auto end() const { return _M_base.end(); } + + // Field width of the first code point in the cluster. + constexpr int + width() const noexcept + { return __field_width(_M_c); } + + private: + _U32_iterator _M_base; + + // Implement the Grapheme Cluster Boundary Rules from Unicode Annex #29 + // http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules + // This implements the rules from TR29 revision 43 in Unicode 15.1.0. + // Return true if there is a break between code point with property p1 + // and code point with property p2. + constexpr bool + _M_is_break(_Gcb_property __p1, _Gcb_property __p2, + _U32_iterator __curr) const + { + using enum _Gcb_property; + + if (__p1 == _Gcb_Control || __p1 == _Gcb_LF) + return true; // Break after Control or LF. + + if (__p1 == _Gcb_CR) + return __p2 != _Gcb_LF; // Do not break between a CR and LF. + + // Rule GB5 + if (__p2 == _Gcb_Control || __p2 == _Gcb_CR || __p2 == _Gcb_LF) + return true; // Break before Control, CR or LF. + + // Rule GB6 + if (__p1 == _Gcb_L) + switch (__p2) + { + case _Gcb_L: + case _Gcb_V: + case _Gcb_LV: + case _Gcb_LVT: + return false; // Do not break Hangul syllable sequences. + default: + return true; + } + + // Rule GB7 + if (__p1 == _Gcb_LV || __p1 == _Gcb_V) + switch (__p2) + { + case _Gcb_V: + case _Gcb_T: + return false; // Do not break Hangul syllable sequences. + default: + return true; + } + + // Rule GB8 + if (__p1 == _Gcb_LVT || __p1 == _Gcb_T) + return __p2 != _Gcb_T; // Do not break Hangul syllable sequences. + + // Rule GB9 + if (__p2 == _Gcb_Extend || __p2 == _Gcb_ZWJ) + return false; // Do not break before extending characters or ZWJ. + + // The following GB9x rules only apply to extended grapheme clusters, + // which is what the C++ standard uses (not legacy grapheme clusters). + + // Rule GB9a + if (__p2 == _Gcb_SpacingMark) + return false; // Do not break before SpacingMarks, + // Rule GB9b + if (__p1 == _Gcb_Prepend) + return false; // or after Prepend characters. + + // Rule GB9c (Unicode 15.1.0) + // Do not break within certain combinations with + // Indic_Conjunct_Break (InCB)=Linker. + if (_M_incb_linker_seen + && __incb_property(_M_c) == _InCB::_Consonant + && __incb_property(*__curr) == _InCB::_Consonant) + { + // Match [_M_base, __curr] against regular expression + // Consonant ([Extend Linker]* Linker [Extend Linker]* Consonant)+ + bool __have_linker = false; + auto __it = _M_base; + while (++__it != __curr) + { + if (__is_incb_linker(*__it)) + __have_linker = true; + else + { + auto __incb = __incb_property(*__it); + if (__incb == _InCB::_Consonant) + __have_linker = false; + else if (__incb != _InCB::_Extend) + break; + } + } + if (__it == __curr && __have_linker) + return false; + } + + // Rule GB11 + // Do not break within emoji modifier sequences + // or emoji zwj sequences. + if (__p1 == _Gcb_ZWJ && _M_xpicto_seq_state == _XPicto::_Matched) + return false; + + // Rules GB12 and GB13 + // Do not break within emoji flag sequences. That is, do not break + // between regional indicator (RI) symbols if there is an odd number + // of RI characters before the break point. + if (__p1 == _Gcb_property::_Gcb_Regional_Indicator && __p1 == __p2) + return (_M_RI_count & 1) == 0; + + // Rule GB999 + return true; // Otherwise, break everywhere. + } + }; + + _Iterator _M_begin; + }; + +} // namespace __v15_1_0 + + // Return the field width of a string. + template + constexpr size_t + __field_width(basic_string_view<_CharT> __s) + { + if (__s.empty()) [[unlikely]] + return 0; + _Grapheme_cluster_view> __gc(__s); + auto __it = __gc.begin(); + const auto __end = __gc.end(); + size_t __n = __it.width(); + while (++__it != __end) + __n += __it.width(); + return __n; + } + + // Truncate a string to at most `__max` field width units, and return the + // resulting field width. + template + constexpr size_t + __truncate(basic_string_view<_CharT>& __s, size_t __max) + { + if (__s.empty()) [[unlikely]] + return 0; + + _Grapheme_cluster_view> __gc(__s); + auto __it = __gc.begin(); + const auto __end = __gc.end(); + size_t __n = __it.width(); + if (__n > __max) + { + __s = {}; + return 0; + } + while (++__it != __end) + { + size_t __n2 = __n + __it.width(); + if (__n2 > __max) + { + __s = basic_string_view<_CharT>(__s.begin(), __it.base()); + return __n; + } + __n = __n2; + } + return __n; + } + + template + consteval bool + __literal_encoding_is_unicode() + { + if constexpr (is_same_v<_CharT, char16_t>) + return true; + else if constexpr (is_same_v<_CharT, char32_t>) + return true; +#ifdef __cpp_char8_t + else if constexpr (is_same_v<_CharT, char8_t>) + return true; +#endif + + const char* __enc = ""; + +#ifdef __GNUC_EXECUTION_CHARSET_NAME + auto __remove_iso10646_prefix = [](const char* __s) { + // GNU iconv allows "ISO-10646/" prefix (case-insensitive). + if (__s[0] == 'I' || __s[0] == 'i') + if (__s[1] == 'S' || __s[1] == 's') + if (__s[2] == 'O' || __s[2] == 'o') + if (string_view(__s + 3).starts_with("-10646/")) + return __s + 10; + return __s; + }; + + if constexpr (is_same_v<_CharT, char>) + __enc = __remove_iso10646_prefix(__GNUC_EXECUTION_CHARSET_NAME); +# if defined _GLIBCXX_USE_WCHAR_T && defined __GNUC_WIDE_EXECUTION_CHARSET_NAME + else + __enc = __remove_iso10646_prefix(__GNUC_WIDE_EXECUTION_CHARSET_NAME); +# endif + + if ((__enc[0] == 'U' || __enc[0] == 'u') + && (__enc[1] == 'T' || __enc[1] == 't') + && (__enc[2] == 'F' || __enc[2] == 'f')) + { + __enc += 3; + if (__enc[0] == '-') + ++__enc; + if (__enc[0] == '8') + return __enc[1] == '\0' || string_view(__enc + 1) == "//"; + else if constexpr (!is_same_v<_CharT, char>) + { + string_view __s(__enc); + if (__s.ends_with("//")) + __s.remove_suffix(2); + return __s == "16" || __s == "32"; + } + } +#elif defined __clang_literal_encoding__ + if constexpr (is_same_v<_CharT, char>) + __enc = __clang_literal_encoding__; +# if defined _GLIBCXX_USE_WCHAR_T && defined __clang_wide_literal_encoding__ + else + __enc = __clang_wide_literal_encoding__; +# endif + // Clang accepts "-fexec-charset=utf-8" but the macro is still uppercase. + string_view __s(__enc); + if (__s == "UTF-8") + return true; + else if constexpr (!is_same_v<_CharT, char>) + return __s == "UTF-16" || __s == "UTF-32"; +#endif + + return false; + } + + consteval bool + __literal_encoding_is_utf8() + { return __literal_encoding_is_unicode(); } + + consteval bool + __literal_encoding_is_extended_ascii() + { + return '0' == 0x30 && 'A' == 0x41 && 'Z' == 0x5a + && 'a' == 0x61 && 'z' == 0x7a; + } + + // https://www.unicode.org/reports/tr22/tr22-8.html#Charset_Alias_Matching + constexpr bool + __charset_alias_match(string_view __a, string_view __b) + { + // Map alphanumeric chars to their base 64 value, everything else to 127. + auto __map = [](char __c, bool& __num) -> unsigned char { + if (__c == '0') [[unlikely]] + return __num ? 0 : 127; + const auto __v = __detail::__from_chars_alnum_to_val(__c); + __num = __v < 10; + return __v; + }; + + auto __ptr_a = __a.begin(), __end_a = __a.end(); + auto __ptr_b = __b.begin(), __end_b = __b.end(); + bool __num_a = false, __num_b = false; + + while (true) + { + // Find the value of the next alphanumeric character in each string. + unsigned char __val_a{}, __val_b{}; + while (__ptr_a != __end_a + && (__val_a = __map(*__ptr_a, __num_a)) == 127) + ++__ptr_a; + while (__ptr_b != __end_b + && (__val_b = __map(*__ptr_b, __num_b)) == 127) + ++__ptr_b; + // Stop when we reach the end of a string, or get a mismatch. + if (__ptr_a == __end_a) + return __ptr_b == __end_b; + else if (__ptr_b == __end_b) + return false; + else if (__val_a != __val_b) + return false; // Found non-matching characters. + ++__ptr_a; + ++__ptr_b; + } + return true; + } + +} // namespace __unicode + +namespace ranges +{ + template + inline constexpr bool + enable_borrowed_range> + = enable_borrowed_range<_Range>; + + template + inline constexpr bool + enable_borrowed_range> + = enable_borrowed_range<_Range>; +} // namespace ranges + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _GLIBCXX_UNICODE_H diff --git a/template/sysroot/include/bits/uniform_int_dist.h b/template/sysroot/include/bits/uniform_int_dist.h new file mode 100644 index 0000000..f19b9c1 --- /dev/null +++ b/template/sysroot/include/bits/uniform_int_dist.h @@ -0,0 +1,468 @@ +// Class template uniform_int_distribution -*- C++ -*- + +// Copyright (C) 2009-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file bits/uniform_int_dist.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H +#define _GLIBCXX_BITS_UNIFORM_INT_DIST_H + +#include +#include +#if __cplusplus > 201703L +# include +#endif +#include // __glibcxx_function_requires + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __cpp_lib_concepts + /// Requirements for a uniform random bit generator. + /** + * @ingroup random_distributions_uniform + * @headerfile random + * @since C++20 + */ + template + concept uniform_random_bit_generator + = invocable<_Gen&> && unsigned_integral> + && requires + { + { _Gen::min() } -> same_as>; + { _Gen::max() } -> same_as>; + requires bool_constant<(_Gen::min() < _Gen::max())>::value; + }; +#endif + + /// @cond undocumented + namespace __detail + { + // Determine whether number is a power of two. + // This is true for zero, which is OK because we want _Power_of_2(n+1) + // to be true if n==numeric_limits<_Tp>::max() and so n+1 wraps around. + template + constexpr bool + _Power_of_2(_Tp __x) + { + return ((__x - 1) & __x) == 0; + } + } + /// @endcond + + /** + * @brief Uniform discrete distribution for random numbers. + * A discrete random distribution on the range @f$[min, max]@f$ with equal + * probability throughout the range. + * + * @ingroup random_distributions_uniform + * @headerfile random + * @since C++11 + */ + template + class uniform_int_distribution + { + static_assert(std::is_integral<_IntType>::value, + "template argument must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + /** Parameter type. */ + struct param_type + { + typedef uniform_int_distribution<_IntType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_IntType __a, + _IntType __b = __gnu_cxx::__int_traits<_IntType>::__max) + : _M_a(__a), _M_b(__b) + { + __glibcxx_assert(_M_a <= _M_b); + } + + result_type + a() const + { return _M_a; } + + result_type + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _IntType _M_a; + _IntType _M_b; + }; + + public: + /** + * @brief Constructs a uniform distribution object. + */ + uniform_int_distribution() : uniform_int_distribution(0) { } + + /** + * @brief Constructs a uniform distribution object. + */ + explicit + uniform_int_distribution(_IntType __a, + _IntType __b + = __gnu_cxx::__int_traits<_IntType>::__max) + : _M_param(__a, __b) + { } + + explicit + uniform_int_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the uniform integer distribution. + */ + void + reset() { } + + result_type + a() const + { return _M_param.a(); } + + result_type + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the inclusive lower bound of the distribution range. + */ + result_type + min() const + { return this->a(); } + + /** + * @brief Returns the inclusive upper bound of the distribution range. + */ + result_type + max() const + { return this->b(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomBitGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomBitGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomBitGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomBitGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomBitGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two uniform integer distributions have + * the same parameters. + */ + friend bool + operator==(const uniform_int_distribution& __d1, + const uniform_int_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomBitGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + // Lemire's nearly divisionless algorithm. + // Returns an unbiased random number from __g downscaled to [0,__range) + // using an unsigned type _Wp twice as wide as unsigned type _Up. + template + static _Up + _S_nd(_Urbg& __g, _Up __range) + { + using _Up_traits = __gnu_cxx::__int_traits<_Up>; + using _Wp_traits = __gnu_cxx::__int_traits<_Wp>; + static_assert(!_Up_traits::__is_signed, "U must be unsigned"); + static_assert(!_Wp_traits::__is_signed, "W must be unsigned"); + static_assert(_Wp_traits::__digits == (2 * _Up_traits::__digits), + "W must be twice as wide as U"); + + // reference: Fast Random Integer Generation in an Interval + // ACM Transactions on Modeling and Computer Simulation 29 (1), 2019 + // https://arxiv.org/abs/1805.10941 + _Wp __product = _Wp(__g()) * _Wp(__range); + _Up __low = _Up(__product); + if (__low < __range) + { + _Up __threshold = -__range % __range; + while (__low < __threshold) + { + __product = _Wp(__g()) * _Wp(__range); + __low = _Up(__product); + } + } + return __product >> _Up_traits::__digits; + } + }; + + template + template + typename uniform_int_distribution<_IntType>::result_type + uniform_int_distribution<_IntType>:: + operator()(_UniformRandomBitGenerator& __urng, + const param_type& __param) + { + typedef typename _UniformRandomBitGenerator::result_type _Gresult_type; + typedef typename make_unsigned::type __utype; + typedef typename common_type<_Gresult_type, __utype>::type __uctype; + + constexpr __uctype __urngmin = _UniformRandomBitGenerator::min(); + constexpr __uctype __urngmax = _UniformRandomBitGenerator::max(); + static_assert( __urngmin < __urngmax, + "Uniform random bit generator must define min() < max()"); + constexpr __uctype __urngrange = __urngmax - __urngmin; + + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + if (__urngrange > __urange) + { + // downscaling + + const __uctype __uerange = __urange + 1; // __urange can be zero + +#if defined __UINT64_TYPE__ && defined __UINT32_TYPE__ +#if __SIZEOF_INT128__ + if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT64_MAX__) + { + // __urng produces values that use exactly 64-bits, + // so use 128-bit integers to downscale to desired range. + __UINT64_TYPE__ __u64erange = __uerange; + __ret = __extension__ _S_nd(__urng, + __u64erange); + } + else +#endif + if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT32_MAX__) + { + // __urng produces values that use exactly 32-bits, + // so use 64-bit integers to downscale to desired range. + __UINT32_TYPE__ __u32erange = __uerange; + __ret = _S_nd<__UINT64_TYPE__>(__urng, __u32erange); + } + else +#endif + { + // fallback case (2 divisions) + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + __ret /= __scaling; + } + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + do + { + const __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + } + else + __ret = __uctype(__urng()) - __urngmin; + + return __ret + __param.a(); + } + + + template + template + void + uniform_int_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomBitGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename _UniformRandomBitGenerator::result_type _Gresult_type; + typedef typename make_unsigned::type __utype; + typedef typename common_type<_Gresult_type, __utype>::type __uctype; + + static_assert( __urng.min() < __urng.max(), + "Uniform random bit generator must define min() < max()"); + + constexpr __uctype __urngmin = __urng.min(); + constexpr __uctype __urngmax = __urng.max(); + constexpr __uctype __urngrange = __urngmax - __urngmin; + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + + if (__urngrange > __urange) + { + if (__detail::_Power_of_2(__urngrange + 1) + && __detail::_Power_of_2(__urange + 1)) + { + while (__f != __t) + { + __ret = __uctype(__urng()) - __urngmin; + *__f++ = (__ret & __urange) + __param.a(); + } + } + else + { + // downscaling + const __uctype __uerange = __urange + 1; // __urange can be zero + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + while (__f != __t) + { + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + *__f++ = __ret / __scaling + __param.a(); + } + } + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + while (__f != __t) + { + do + { + constexpr __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + *__f++ = __ret; + } + } + else + while (__f != __t) + *__f++ = __uctype(__urng()) - __urngmin + __param.a(); + } + + // operator!= and operator<< and operator>> are defined in + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/template/sysroot/include/bits/unique_ptr.h b/template/sysroot/include/bits/unique_ptr.h new file mode 100644 index 0000000..0f600db --- /dev/null +++ b/template/sysroot/include/bits/unique_ptr.h @@ -0,0 +1,1183 @@ + +// unique_ptr implementation -*- C++ -*- + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unique_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _UNIQUE_PTR_H +#define _UNIQUE_PTR_H 1 + +#include +#include +#include +#include +#include +#include +#if __cplusplus >= 202002L +# include +# if _GLIBCXX_HOSTED +# include +# endif +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup pointer_abstractions + * @{ + */ + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + template class auto_ptr; +#pragma GCC diagnostic pop +#endif + + /** Primary template of default_delete, used by unique_ptr for single objects + * + * @headerfile memory + * @since C++11 + */ + template + struct default_delete + { + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for objects of another type, `_Up`, + * only if `_Up*` is convertible to `_Tp*`. + */ + template>> + _GLIBCXX23_CONSTEXPR + default_delete(const default_delete<_Up>&) noexcept { } + + /// Calls `delete __ptr` + _GLIBCXX23_CONSTEXPR + void + operator()(_Tp* __ptr) const + { + static_assert(!is_void<_Tp>::value, + "can't delete pointer to incomplete type"); + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete __ptr; + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + + /** Specialization of default_delete for arrays, used by `unique_ptr` + * + * @headerfile memory + * @since C++11 + */ + template + struct default_delete<_Tp[]> + { + public: + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for arrays of another type, such as + * a const-qualified version of `_Tp`. + * + * Conversions from types derived from `_Tp` are not allowed because + * it is undefined to `delete[]` an array of derived types through a + * pointer to the base type. + */ + template>> + _GLIBCXX23_CONSTEXPR + default_delete(const default_delete<_Up[]>&) noexcept { } + + /// Calls `delete[] __ptr` + template + _GLIBCXX23_CONSTEXPR + typename enable_if::value>::type + operator()(_Up* __ptr) const + { + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete [] __ptr; + } + }; + + /// @cond undocumented + + // Manages the pointer and deleter of a unique_ptr + template + class __uniq_ptr_impl + { + template + struct _Ptr + { + using type = _Up*; + }; + + template + struct + _Ptr<_Up, _Ep, __void_t::type::pointer>> + { + using type = typename remove_reference<_Ep>::type::pointer; + }; + + public: + using _DeleterConstraint = enable_if< + __and_<__not_>, + is_default_constructible<_Dp>>::value>; + + using pointer = typename _Ptr<_Tp, _Dp>::type; + + static_assert( !is_rvalue_reference<_Dp>::value, + "unique_ptr's deleter type must be a function object type" + " or an lvalue reference type" ); + + __uniq_ptr_impl() = default; + _GLIBCXX23_CONSTEXPR + __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } + + template + _GLIBCXX23_CONSTEXPR + __uniq_ptr_impl(pointer __p, _Del&& __d) + : _M_t(__p, std::forward<_Del>(__d)) { } + + _GLIBCXX23_CONSTEXPR + __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept + : _M_t(std::move(__u._M_t)) + { __u._M_ptr() = nullptr; } + + _GLIBCXX23_CONSTEXPR + __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept + { + reset(__u.release()); + _M_deleter() = std::forward<_Dp>(__u._M_deleter()); + return *this; + } + + _GLIBCXX23_CONSTEXPR + pointer& _M_ptr() noexcept { return std::get<0>(_M_t); } + _GLIBCXX23_CONSTEXPR + pointer _M_ptr() const noexcept { return std::get<0>(_M_t); } + _GLIBCXX23_CONSTEXPR + _Dp& _M_deleter() noexcept { return std::get<1>(_M_t); } + _GLIBCXX23_CONSTEXPR + const _Dp& _M_deleter() const noexcept { return std::get<1>(_M_t); } + + _GLIBCXX23_CONSTEXPR + void reset(pointer __p) noexcept + { + const pointer __old_p = _M_ptr(); + _M_ptr() = __p; + if (__old_p) + _M_deleter()(__old_p); + } + + _GLIBCXX23_CONSTEXPR + pointer release() noexcept + { + pointer __p = _M_ptr(); + _M_ptr() = nullptr; + return __p; + } + + _GLIBCXX23_CONSTEXPR + void + swap(__uniq_ptr_impl& __rhs) noexcept + { + using std::swap; + swap(this->_M_ptr(), __rhs._M_ptr()); + swap(this->_M_deleter(), __rhs._M_deleter()); + } + + private: + tuple _M_t; + }; + + // Defines move construction + assignment as either defaulted or deleted. + template ::value, + bool = is_move_assignable<_Dp>::value> + struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + /// @endcond + + // 20.7.1.2 unique_ptr for single objects. + + /// A move-only smart pointer that manages unique ownership of a resource. + /// @headerfile memory + /// @since C++11 + template > + class unique_ptr + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + private: + // helper template for detecting a safe conversion from another + // unique_ptr + template + using __safe_conversion_up = __and_< + is_convertible::pointer, pointer>, + __not_> + >; + + public: + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * + * The deleter will be value-initialized. + */ + template> + _GLIBCXX23_CONSTEXPR + explicit + unique_ptr(pointer __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template>> + _GLIBCXX23_CONSTEXPR + unique_ptr(pointer __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d An rvalue reference to a (non-reference) deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template>> + _GLIBCXX23_CONSTEXPR + unique_ptr(pointer __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(__p, std::move(__d)) + { } + + template::type> + _GLIBCXX23_CONSTEXPR + unique_ptr(pointer, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + // Move constructors. + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /** @brief Converting constructor from another type + * + * Requires that the pointer owned by @p __u is convertible to the + * type of pointer owned by this object, @p __u does not own an array, + * and @p __u has a compatible deleter type. + */ + template, + __conditional_t::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>>> + _GLIBCXX23_CONSTEXPR + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// Converting constructor from @c auto_ptr + template, is_same<_Dp, default_delete<_Tp>>>> + unique_ptr(auto_ptr<_Up>&& __u) noexcept; +#pragma GCC diagnostic pop +#endif + + /// Destructor, invokes the deleter if the stored pointer is not null. +#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~unique_ptr() noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(std::move(__ptr)); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to a non-array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + _GLIBCXX23_CONSTEXPR + typename enable_if< __and_< + __safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + _GLIBCXX23_CONSTEXPR + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Dereference the stored pointer. + _GLIBCXX23_CONSTEXPR + typename add_lvalue_reference::type + operator*() const noexcept(noexcept(*std::declval())) + { + __glibcxx_assert(get() != pointer()); + return *get(); + } + + /// Return the stored pointer. + _GLIBCXX23_CONSTEXPR + pointer + operator->() const noexcept + { + _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); + return get(); + } + + /// Return the stored pointer. + _GLIBCXX23_CONSTEXPR + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + _GLIBCXX23_CONSTEXPR + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + _GLIBCXX23_CONSTEXPR + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + _GLIBCXX23_CONSTEXPR + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + _GLIBCXX23_CONSTEXPR + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + _GLIBCXX23_CONSTEXPR + void + reset(pointer __p = pointer()) noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + _M_t.reset(std::move(__p)); + } + + /// Exchange the pointer and deleter with another object. + _GLIBCXX23_CONSTEXPR + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + + private: +#ifdef __glibcxx_out_ptr + template + friend class out_ptr_t; + template + friend class inout_ptr_t; +#endif + }; + + // 20.7.1.3 unique_ptr for array objects with a runtime length + // [unique.ptr.runtime] + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + + /// A move-only smart pointer that manages unique ownership of an array. + /// @headerfile memory + /// @since C++11 + template + class unique_ptr<_Tp[], _Dp> + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + // like is_base_of<_Tp, _Up> but false if unqualified types are the same + template + using __is_derived_Tp + = __and_< is_base_of<_Tp, _Up>, + __not_, __remove_cv_t<_Up>>> >; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + // helper template for detecting a safe conversion from another + // unique_ptr + template, + typename _UP_pointer = typename _UPtr::pointer, + typename _UP_element_type = typename _UPtr::element_type> + using __safe_conversion_up = __and_< + is_array<_Up>, + is_same, + is_same<_UP_pointer, _UP_element_type*>, + is_convertible<_UP_element_type(*)[], element_type(*)[]> + >; + + // helper template for detecting a safe conversion from a raw pointer + template + using __safe_conversion_raw = __and_< + __or_<__or_, + is_same<_Up, nullptr_t>>, + __and_, + is_same, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[]> + > + > + >; + + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * + * The deleter will be value-initialized. + */ + template, + typename = typename enable_if< + __safe_conversion_raw<_Up>::value, bool>::type> + _GLIBCXX23_CONSTEXPR + explicit + unique_ptr(_Up __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template, + is_copy_constructible<_Del>>> + _GLIBCXX23_CONSTEXPR + unique_ptr(_Up __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template, + is_move_constructible<_Del>>> + _GLIBCXX23_CONSTEXPR + unique_ptr(_Up __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(std::move(__p), std::move(__d)) + { } + + template::type, + typename = _Require<__safe_conversion_raw<_Up>>> + unique_ptr(_Up, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + template, + __conditional_t::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>>> + _GLIBCXX23_CONSTEXPR + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + + /// Destructor, invokes the deleter if the stored pointer is not null. +#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~unique_ptr() + { + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(__ptr); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& + operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to an array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + _GLIBCXX23_CONSTEXPR + typename + enable_if<__and_<__safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + _GLIBCXX23_CONSTEXPR + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Access an element of owned array. + _GLIBCXX23_CONSTEXPR + typename std::add_lvalue_reference::type + operator[](size_t __i) const + { + __glibcxx_assert(get() != pointer()); + return get()[__i]; + } + + /// Return the stored pointer. + _GLIBCXX23_CONSTEXPR + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + _GLIBCXX23_CONSTEXPR + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + _GLIBCXX23_CONSTEXPR + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + _GLIBCXX23_CONSTEXPR + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + _GLIBCXX23_CONSTEXPR + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + template , + __and_, + is_pointer<_Up>, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[] + > + > + > + >> + _GLIBCXX23_CONSTEXPR + void + reset(_Up __p) noexcept + { _M_t.reset(std::move(__p)); } + + _GLIBCXX23_CONSTEXPR + void reset(nullptr_t = nullptr) noexcept + { reset(pointer()); } + + /// Exchange the pointer and deleter with another object. + _GLIBCXX23_CONSTEXPR + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + + private: +#ifdef __glibcxx_out_ptr + template friend class out_ptr_t; + template friend class inout_ptr_t; +#endif + }; + + /// @{ + /// @relates unique_ptr + + /// Swap overload for unique_ptr + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + _GLIBCXX23_CONSTEXPR + typename enable_if<__is_swappable<_Dp>::value>::type +#else + void +#endif + swap(unique_ptr<_Tp, _Dp>& __x, + unique_ptr<_Tp, _Dp>& __y) noexcept + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if::value>::type + swap(unique_ptr<_Tp, _Dp>&, + unique_ptr<_Tp, _Dp>&) = delete; +#endif + + /// Equality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() == __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return !__x; } + +#ifndef __cpp_lib_three_way_comparison + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD + inline bool + operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return !__x; } + + /// Inequality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD + inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() != __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD + inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return (bool)__x; } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD + inline bool + operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return (bool)__x; } +#endif // three way comparison + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { + typedef typename + std::common_type::pointer, + typename unique_ptr<_Up, _Ep>::pointer>::type _CT; + return std::less<_CT>()(__x.get(), __y.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(nullptr < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(__x < nullptr); } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return (__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__x < __y); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR + inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(__x < nullptr); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(nullptr < __x); } + +#ifdef __cpp_lib_three_way_comparison + template + requires three_way_comparable_with::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + _GLIBCXX23_CONSTEXPR + inline + compare_three_way_result_t::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return compare_three_way()(__x.get(), __y.get()); } + + template + requires three_way_comparable::pointer> + _GLIBCXX23_CONSTEXPR + inline + compare_three_way_result_t::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + using pointer = typename unique_ptr<_Tp, _Dp>::pointer; + return compare_three_way()(__x.get(), static_cast(nullptr)); + } +#endif + /// @} relates unique_ptr + + /// @cond undocumented + template::__enable_hash_call> + struct __uniq_ptr_hash +#if ! _GLIBCXX_INLINE_VERSION + : private __poison_hash<_Ptr> +#endif + { + size_t + operator()(const _Up& __u) const + noexcept(noexcept(std::declval>()(std::declval<_Ptr>()))) + { return hash<_Ptr>()(__u.get()); } + }; + + template + struct __uniq_ptr_hash<_Up, _Ptr, false> + : private __poison_hash<_Ptr> + { }; + /// @endcond + + /// std::hash specialization for unique_ptr. + template + struct hash> + : public __hash_base>, + public __uniq_ptr_hash> + { }; + +#ifdef __glibcxx_make_unique // C++ >= 14 && HOSTED + /// @cond undocumented +namespace __detail +{ + template + struct _MakeUniq + { typedef unique_ptr<_Tp> __single_object; }; + + template + struct _MakeUniq<_Tp[]> + { typedef unique_ptr<_Tp[]> __array; }; + + template + struct _MakeUniq<_Tp[_Bound]> + { struct __invalid_type { }; }; + + template + using __unique_ptr_t = typename _MakeUniq<_Tp>::__single_object; + template + using __unique_ptr_array_t = typename _MakeUniq<_Tp>::__array; + template + using __invalid_make_unique_t = typename _MakeUniq<_Tp>::__invalid_type; +} + /// @endcond + + /** Create an object owned by a `unique_ptr`. + * @tparam _Tp A non-array object type. + * @param __args Constructor arguments for the new object. + * @returns A `unique_ptr<_Tp>` that owns the new object. + * @since C++14 + * @relates unique_ptr + */ + template + _GLIBCXX23_CONSTEXPR + inline __detail::__unique_ptr_t<_Tp> + make_unique(_Args&&... __args) + { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } + + /** Create an array owned by a `unique_ptr`. + * @tparam _Tp An array type of unknown bound, such as `U[]`. + * @param __num The number of elements of type `U` in the new array. + * @returns A `unique_ptr` that owns the new array. + * @since C++14 + * @relates unique_ptr + * + * The array elements are value-initialized. + */ + template + _GLIBCXX23_CONSTEXPR + inline __detail::__unique_ptr_array_t<_Tp> + make_unique(size_t __num) + { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } + + /** Disable std::make_unique for arrays of known bound. + * @tparam _Tp An array type of known bound, such as `U[N]`. + * @since C++14 + * @relates unique_ptr + */ + template + __detail::__invalid_make_unique_t<_Tp> + make_unique(_Args&&...) = delete; + +#if __cplusplus > 201703L + /** Create a default-initialied object owned by a `unique_ptr`. + * @tparam _Tp A non-array object type. + * @returns A `unique_ptr<_Tp>` that owns the new object. + * @since C++20 + * @relates unique_ptr + */ + template + _GLIBCXX23_CONSTEXPR + inline __detail::__unique_ptr_t<_Tp> + make_unique_for_overwrite() + { return unique_ptr<_Tp>(new _Tp); } + + /** Create a default-initialized array owned by a `unique_ptr`. + * @tparam _Tp An array type of unknown bound, such as `U[]`. + * @param __num The number of elements of type `U` in the new array. + * @returns A `unique_ptr` that owns the new array. + * @since C++20 + * @relates unique_ptr + */ + template + _GLIBCXX23_CONSTEXPR + inline __detail::__unique_ptr_array_t<_Tp> + make_unique_for_overwrite(size_t __num) + { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]); } + + /** Disable std::make_unique_for_overwrite for arrays of known bound. + * @tparam _Tp An array type of known bound, such as `U[N]`. + * @since C++20 + * @relates unique_ptr + */ + template + __detail::__invalid_make_unique_t<_Tp> + make_unique_for_overwrite(_Args&&...) = delete; +#endif // C++20 + +#endif // C++14 && HOSTED + +#if __cplusplus > 201703L && __cpp_concepts && _GLIBCXX_HOSTED + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2948. unique_ptr does not define operator<< for stream output + /// Stream output operator for unique_ptr + /// @relates unique_ptr + /// @since C++20 + template + inline basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const unique_ptr<_Tp, _Dp>& __p) + requires requires { __os << __p.get(); } + { + __os << __p.get(); + return __os; + } +#endif // C++20 && HOSTED + +#if __cpp_variable_templates + template + static constexpr bool __is_unique_ptr = false; + template + static constexpr bool __is_unique_ptr> = true; +#endif + + /// @} group pointer_abstractions + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // unique_ptr into a variant. + template + struct _Never_valueless_alt> + : std::true_type + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _UNIQUE_PTR_H */ diff --git a/template/sysroot/include/bits/uses_allocator.h b/template/sysroot/include/bits/uses_allocator.h new file mode 100644 index 0000000..2ebb75f --- /dev/null +++ b/template/sysroot/include/bits/uses_allocator.h @@ -0,0 +1,202 @@ +// Uses-allocator Construction -*- C++ -*- + +// Copyright (C) 2010-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/uses_allocator_args.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _USES_ALLOCATOR_H +#define _USES_ALLOCATOR_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +/// @cond undocumented + + // This is used for std::experimental::erased_type from Library Fundamentals. + struct __erased_type { }; + + // This also supports the "type-erased allocator" protocol from the + // Library Fundamentals TS, where allocator_type is erased_type. + // The second condition will always be false for types not using the TS. + template + using __is_erased_or_convertible + = __or_, is_same<_Tp, __erased_type>>; + + /// [allocator.tag] + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + + _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = + allocator_arg_t(); + + template> + struct __uses_allocator_helper + : false_type { }; + + template + struct __uses_allocator_helper<_Tp, _Alloc, + __void_t> + : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type + { }; + + /// [allocator.uses.trait] + template + struct uses_allocator + : __uses_allocator_helper<_Tp, _Alloc>::type + { }; + + struct __uses_alloc_base { }; + + struct __uses_alloc0 : __uses_alloc_base + { + struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a; + }; + + template + struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc; + + template + struct __uses_alloc + : __conditional_t< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, + __uses_alloc1<_Alloc>, + __uses_alloc2<_Alloc>> + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2586. Wrong value category used in scoped_allocator_adaptor::construct + static_assert(__or_< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, + is_constructible<_Tp, _Args..., const _Alloc&>>::value, + "construction with an allocator must be possible" + " if uses_allocator is true"); + }; + + template + struct __uses_alloc + : __uses_alloc0 { }; + + template + using __uses_alloc_t = + __uses_alloc::value, _Tp, _Alloc, _Args...>; + + template + _GLIBCXX20_CONSTEXPR + inline __uses_alloc_t<_Tp, _Alloc, _Args...> + __use_alloc(const _Alloc& __a) + { + __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; + __ret._M_a = std::__addressof(__a); + return __ret; + } + + template + void + __use_alloc(const _Alloc&&) = delete; + +#if __cplusplus > 201402L + template + inline constexpr bool uses_allocator_v = + uses_allocator<_Tp, _Alloc>::value; +#endif // C++17 + + template class _Predicate, + typename _Tp, typename _Alloc, typename... _Args> + struct __is_uses_allocator_predicate + : __conditional_t::value, + __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, + _Predicate<_Tp, _Args..., _Alloc>>, + _Predicate<_Tp, _Args...>> { }; + + template + struct __is_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = + __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + struct __is_nothrow_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool + __is_nothrow_uses_allocator_constructible_v = + __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + void __uses_allocator_construct_impl(__uses_alloc0, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } + + template + void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { + ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, + std::forward<_Args>(__args)...); + } + + template + void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } + + template + void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, + _Args&&... __args) + { + std::__uses_allocator_construct_impl( + std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr, + std::forward<_Args>(__args)...); + } + +/// @endcond +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/template/sysroot/include/bits/uses_allocator_args.h b/template/sysroot/include/bits/uses_allocator_args.h new file mode 100644 index 0000000..92097c9 --- /dev/null +++ b/template/sysroot/include/bits/uses_allocator_args.h @@ -0,0 +1,248 @@ +// Utility functions for uses-allocator construction -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/uses_allocator_args.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _USES_ALLOCATOR_ARGS +#define _USES_ALLOCATOR_ARGS 1 + +#pragma GCC system_header + +#include + +#ifdef __glibcxx_make_obj_using_allocator // C++ >= 20 && concepts +#include // for placement operator new +#include // for tuple, make_tuple, make_from_tuple +#include // construct_at +#include // pair + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + concept _Std_pair = __is_pair>; + +/** @addtogroup allocators + * @{ + */ + template + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + _Args&&... __args) noexcept + requires (! _Std_pair<_Tp>) + { + if constexpr (uses_allocator_v, _Alloc>) + { + if constexpr (is_constructible_v<_Tp, allocator_arg_t, + const _Alloc&, _Args...>) + { + return tuple( + allocator_arg, __a, std::forward<_Args>(__args)...); + } + else + { + static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>, + "construction with an allocator must be possible" + " if uses_allocator is true"); + + return tuple<_Args&&..., const _Alloc&>( + std::forward<_Args>(__args)..., __a); + } + } + else + { + static_assert(is_constructible_v<_Tp, _Args...>); + + return tuple<_Args&&...>(std::forward<_Args>(__args)...); + } + } + + template<_Std_pair _Tp, typename _Alloc, typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept; + + template<_Std_pair _Tp, typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc&) noexcept; + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept; + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, + const pair<_Up, _Vp>&) noexcept; + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept; + +#if __cplusplus > 202002L + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, + pair<_Up, _Vp>&) noexcept; + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, const pair<_Up, _Vp>&&) noexcept; +#endif // C++23 + + template<_Std_pair _Tp, typename _Alloc, typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::apply([&__a](auto&&... __args1) { + return std::uses_allocator_construction_args<_Tp1>( + __a, std::forward(__args1)...); + }, std::forward<_Tuple1>(__x)), + std::apply([&__a](auto&&... __args2) { + return std::uses_allocator_construction_args<_Tp2>( + __a, std::forward(__args2)...); + }, std::forward<_Tuple2>(__y))); + } + + template<_Std_pair _Tp, typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a), + std::uses_allocator_construction_args<_Tp2>(__a)); + } + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v) + noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::forward<_Up>(__u)), + std::uses_allocator_construction_args<_Tp2>(__a, + std::forward<_Vp>(__v))); + } + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + const pair<_Up, _Vp>& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), + std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); + } + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + pair<_Up, _Vp>&& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3527. uses_allocator_construction_args handles rvalue pairs + // of rvalue references incorrectly + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::get<0>(std::move(__pr))), + std::uses_allocator_construction_args<_Tp2>(__a, + std::get<1>(std::move(__pr)))); + } + +#if __cplusplus > 202002L + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + pair<_Up, _Vp>& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), + std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); + } + + template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + const pair<_Up, _Vp>&& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::get<0>(std::move(__pr))), + std::uses_allocator_construction_args<_Tp2>(__a, + std::get<1>(std::move(__pr)))); + } +#endif // C++23 + + template + constexpr _Tp + make_obj_using_allocator(const _Alloc& __a, _Args&&... __args) + { + return std::make_from_tuple<_Tp>( + std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } + + template + constexpr _Tp* + uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a, + _Args&&... __args) + { + return std::apply([&](auto&&... __xs) { + return std::construct_at(__p, std::forward(__xs)...); + }, std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } +/// @} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __glibcxx_make_obj_using_allocator +#endif // _USES_ALLOCATOR_ARGS diff --git a/template/sysroot/include/bits/utility.h b/template/sysroot/include/bits/utility.h new file mode 100644 index 0000000..9f3b992 --- /dev/null +++ b/template/sysroot/include/bits/utility.h @@ -0,0 +1,287 @@ +// Utilities used throughout the library -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/utility.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + * + * This file contains the parts of `` needed by other headers, + * so they don't need to include the whole of ``. + */ + +#ifndef _GLIBCXX_UTILITY_H +#define _GLIBCXX_UTILITY_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Finds the size of a given tuple type. + template + struct tuple_size; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2313. tuple_size should always derive from integral_constant + // 2770. tuple_size specialization is not SFINAE compatible + + template::type, + typename = typename enable_if::value>::type, + size_t = tuple_size<_Tp>::value> + using __enable_if_has_tuple_size = _Tp; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + +#if __cplusplus >= 201703L + template + inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; +#endif + + /// Gives the type of the ith element of a given tuple type. + template + struct tuple_element; + + // Duplicate of C++14's tuple_element_t for internal use in C++11 mode + template + using __tuple_element_t = typename tuple_element<__i, _Tp>::type; + + template + struct tuple_element<__i, const _Tp> + { + using type = const __tuple_element_t<__i, _Tp>; + }; + + template + struct tuple_element<__i, volatile _Tp> + { + using type = volatile __tuple_element_t<__i, _Tp>; + }; + + template + struct tuple_element<__i, const volatile _Tp> + { + using type = const volatile __tuple_element_t<__i, _Tp>; + }; + +#if __cplusplus >= 201402L + + // Return the index of _Tp in _Types, if it occurs exactly once. + // Otherwise, return sizeof...(_Types). + template + constexpr size_t + __find_uniq_type_in_pack() + { + constexpr size_t __sz = sizeof...(_Types); + constexpr bool __found[__sz] = { __is_same(_Tp, _Types) ... }; + size_t __n = __sz; + for (size_t __i = 0; __i < __sz; ++__i) + { + if (__found[__i]) + { + if (__n < __sz) // more than one _Tp found + return __sz; + __n = __i; + } + } + return __n; + } +#endif // C++14 + +// The standard says this macro and alias template should be in but we +// define them here, to be available in , and too. +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 3378. tuple_size_v/tuple_element_t should be available when +// tuple_size/tuple_element are +#ifdef __glibcxx_tuple_element_t // C++ >= 14 + template + using tuple_element_t = typename tuple_element<__i, _Tp>::type; +#endif + + // Stores a tuple of indices. Used by tuple and pair, and by bind() to + // extract the elements in a tuple. + template struct _Index_tuple { }; + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + { +#if __has_builtin(__make_integer_seq) + template + using _IdxTuple = _Index_tuple<_Indices...>; + + // Clang defines __make_integer_seq for this purpose. + using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; +#else + // For GCC and other compilers, use __integer_pack instead. + using __type = _Index_tuple<__integer_pack(_Num)...>; +#endif + }; + +#ifdef __glibcxx_integer_sequence // C++ >= 14 + + /// Class template integer_sequence + template + struct integer_sequence + { +#if __cplusplus >= 202002L + static_assert(is_integral_v<_Tp>); +#endif + typedef _Tp value_type; + static constexpr size_t size() noexcept { return sizeof...(_Idx); } + }; + + /// Alias template make_integer_sequence + template + using make_integer_sequence +#if __has_builtin(__make_integer_seq) + = __make_integer_seq; +#else + = integer_sequence<_Tp, __integer_pack(_Num)...>; +#endif + + /// Alias template index_sequence + template + using index_sequence = integer_sequence; + + /// Alias template make_index_sequence + template + using make_index_sequence = make_integer_sequence; + + /// Alias template index_sequence_for + template + using index_sequence_for = make_index_sequence; +#endif // __glibcxx_integer_sequence + +#if __cplusplus >= 201703L + + struct in_place_t { + explicit in_place_t() = default; + }; + + inline constexpr in_place_t in_place{}; + + template struct in_place_type_t + { + explicit in_place_type_t() = default; + }; + + template + inline constexpr in_place_type_t<_Tp> in_place_type{}; + + template struct in_place_index_t + { + explicit in_place_index_t() = default; + }; + + template + inline constexpr in_place_index_t<_Idx> in_place_index{}; + + template + inline constexpr bool __is_in_place_type_v = false; + + template + inline constexpr bool __is_in_place_type_v> = true; + + template + using __is_in_place_type = bool_constant<__is_in_place_type_v<_Tp>>; + + template + inline constexpr bool __is_in_place_index_v = false; + + template + inline constexpr bool __is_in_place_index_v> = true; + +#endif // C++17 + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__type_pack_element) + template + struct _Nth_type + { using type = __type_pack_element<_Np, _Types...>; }; +#else + template + struct _Nth_type + { }; + + template + struct _Nth_type<0, _Tp0, _Rest...> + { using type = _Tp0; }; + + template + struct _Nth_type<1, _Tp0, _Tp1, _Rest...> + { using type = _Tp1; }; + + template + struct _Nth_type<2, _Tp0, _Tp1, _Tp2, _Rest...> + { using type = _Tp2; }; + + template +#if __cpp_concepts + requires (_Np >= 3) +#endif + struct _Nth_type<_Np, _Tp0, _Tp1, _Tp2, _Rest...> + : _Nth_type<_Np - 3, _Rest...> + { }; + +#if ! __cpp_concepts // Need additional specializations to avoid ambiguities. + template + struct _Nth_type<0, _Tp0, _Tp1, _Tp2, _Rest...> + { using type = _Tp0; }; + + template + struct _Nth_type<1, _Tp0, _Tp1, _Tp2, _Rest...> + { using type = _Tp1; }; +#endif +#endif + +#if __glibcxx_ranges + namespace ranges::__detail + { + template + inline constexpr bool __is_subrange = false; + } // namespace __detail +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 +#endif /* _GLIBCXX_UTILITY_H */ diff --git a/template/sysroot/include/bits/version.h b/template/sysroot/include/bits/version.h new file mode 100644 index 0000000..ad418d4 --- /dev/null +++ b/template/sysroot/include/bits/version.h @@ -0,0 +1,2006 @@ +// Copyright (C) 2023-2024 Free Software Foundation, Inc. + +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// DO NOT EDIT THIS FILE (version.h) +// +// It has been AutoGen-ed +// From the definitions version.def +// and the template file version.tpl + +/** @file bits/version.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{version} + */ + +// Usage guide: +// +// In your usual header, do something like: +// +// #define __glibcxx_want_ranges +// #define __glibcxx_want_concepts +// #include +// +// This will generate the FTMs you named, and let you use them in your code as +// if it was user code. All macros are also exposed under __glibcxx_NAME even +// if unwanted, to permit bits and other FTMs to depend on them for condtional +// computation without exposing extra FTMs to user code. + +#pragma GCC system_header + +#include + +#if !defined(__cpp_lib_incomplete_container_elements) +# if _GLIBCXX_HOSTED +# define __glibcxx_incomplete_container_elements 201505L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_incomplete_container_elements) +# define __cpp_lib_incomplete_container_elements 201505L +# endif +# endif +#endif /* !defined(__cpp_lib_incomplete_container_elements) && defined(__glibcxx_want_incomplete_container_elements) */ +#undef __glibcxx_want_incomplete_container_elements + +#if !defined(__cpp_lib_uncaught_exceptions) +# if ((defined(__STRICT_ANSI__) && __cplusplus >= 201703L) || (!defined(__STRICT_ANSI__) && __cplusplus >= 199711L)) +# define __glibcxx_uncaught_exceptions 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_uncaught_exceptions) +# define __cpp_lib_uncaught_exceptions 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_uncaught_exceptions) && defined(__glibcxx_want_uncaught_exceptions) */ +#undef __glibcxx_want_uncaught_exceptions + +#if !defined(__cpp_lib_allocator_traits_is_always_equal) +# if (__cplusplus >= 201103L) +# define __glibcxx_allocator_traits_is_always_equal 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_allocator_traits_is_always_equal) +# define __cpp_lib_allocator_traits_is_always_equal 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_allocator_traits_is_always_equal) && defined(__glibcxx_want_allocator_traits_is_always_equal) */ +#undef __glibcxx_want_allocator_traits_is_always_equal + +#if !defined(__cpp_lib_is_null_pointer) +# if (__cplusplus >= 201103L) +# define __glibcxx_is_null_pointer 201309L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_null_pointer) +# define __cpp_lib_is_null_pointer 201309L +# endif +# endif +#endif /* !defined(__cpp_lib_is_null_pointer) && defined(__glibcxx_want_is_null_pointer) */ +#undef __glibcxx_want_is_null_pointer + +#if !defined(__cpp_lib_result_of_sfinae) +# if (__cplusplus >= 201103L) +# define __glibcxx_result_of_sfinae 201210L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_result_of_sfinae) +# define __cpp_lib_result_of_sfinae 201210L +# endif +# endif +#endif /* !defined(__cpp_lib_result_of_sfinae) && defined(__glibcxx_want_result_of_sfinae) */ +#undef __glibcxx_want_result_of_sfinae + +#if !defined(__cpp_lib_shared_ptr_arrays) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_shared_ptr_arrays 201707L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shared_ptr_arrays) +# define __cpp_lib_shared_ptr_arrays 201707L +# endif +# elif (__cplusplus >= 201103L) && _GLIBCXX_HOSTED +# define __glibcxx_shared_ptr_arrays 201611L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shared_ptr_arrays) +# define __cpp_lib_shared_ptr_arrays 201611L +# endif +# endif +#endif /* !defined(__cpp_lib_shared_ptr_arrays) && defined(__glibcxx_want_shared_ptr_arrays) */ +#undef __glibcxx_want_shared_ptr_arrays + +#if !defined(__cpp_lib_is_swappable) +# if ((defined(__STRICT_ANSI__) && __cplusplus >= 201703L) || (!defined(__STRICT_ANSI__) && __cplusplus >= 201103L)) +# define __glibcxx_is_swappable 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_swappable) +# define __cpp_lib_is_swappable 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_is_swappable) && defined(__glibcxx_want_is_swappable) */ +#undef __glibcxx_want_is_swappable + +#if !defined(__cpp_lib_void_t) +# if ((defined(__STRICT_ANSI__) && __cplusplus >= 201703L) || (!defined(__STRICT_ANSI__) && __cplusplus >= 201103L)) +# define __glibcxx_void_t 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_void_t) +# define __cpp_lib_void_t 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_void_t) && defined(__glibcxx_want_void_t) */ +#undef __glibcxx_want_void_t + +#if !defined(__cpp_lib_enable_shared_from_this) +# if ((defined(__STRICT_ANSI__) && __cplusplus >= 201703L) || (!defined(__STRICT_ANSI__) && __cplusplus >= 201103L)) && _GLIBCXX_HOSTED +# define __glibcxx_enable_shared_from_this 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_enable_shared_from_this) +# define __cpp_lib_enable_shared_from_this 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_enable_shared_from_this) && defined(__glibcxx_want_enable_shared_from_this) */ +#undef __glibcxx_want_enable_shared_from_this + +#if !defined(__cpp_lib_math_spec_funcs) +# if (__cplusplus >= 201103L) +# define __glibcxx_math_spec_funcs 201003L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_math_spec_funcs) +# define __STDCPP_MATH_SPEC_FUNCS__ 201003L +# endif +# endif +#endif /* !defined(__cpp_lib_math_spec_funcs) && defined(__glibcxx_want_math_spec_funcs) */ +#undef __glibcxx_want_math_spec_funcs + +#if !defined(__cpp_lib_coroutine) +# if (__cplusplus >= 201402L) && (__cpp_impl_coroutine) +# define __glibcxx_coroutine 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_coroutine) +# define __cpp_lib_coroutine 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_coroutine) && defined(__glibcxx_want_coroutine) */ +#undef __glibcxx_want_coroutine + +#if !defined(__cpp_lib_exchange_function) +# if (__cplusplus >= 201402L) +# define __glibcxx_exchange_function 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_exchange_function) +# define __cpp_lib_exchange_function 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_exchange_function) && defined(__glibcxx_want_exchange_function) */ +#undef __glibcxx_want_exchange_function + +#if !defined(__cpp_lib_integer_sequence) +# if (__cplusplus >= 201402L) +# define __glibcxx_integer_sequence 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_integer_sequence) +# define __cpp_lib_integer_sequence 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_integer_sequence) && defined(__glibcxx_want_integer_sequence) */ +#undef __glibcxx_want_integer_sequence + +#if !defined(__cpp_lib_integral_constant_callable) +# if (__cplusplus >= 201402L) +# define __glibcxx_integral_constant_callable 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_integral_constant_callable) +# define __cpp_lib_integral_constant_callable 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_integral_constant_callable) && defined(__glibcxx_want_integral_constant_callable) */ +#undef __glibcxx_want_integral_constant_callable + +#if !defined(__cpp_lib_is_final) +# if (__cplusplus >= 201402L) +# define __glibcxx_is_final 201402L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_final) +# define __cpp_lib_is_final 201402L +# endif +# endif +#endif /* !defined(__cpp_lib_is_final) && defined(__glibcxx_want_is_final) */ +#undef __glibcxx_want_is_final + +#if !defined(__cpp_lib_make_reverse_iterator) +# if (__cplusplus >= 201402L) +# define __glibcxx_make_reverse_iterator 201402L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_reverse_iterator) +# define __cpp_lib_make_reverse_iterator 201402L +# endif +# endif +#endif /* !defined(__cpp_lib_make_reverse_iterator) && defined(__glibcxx_want_make_reverse_iterator) */ +#undef __glibcxx_want_make_reverse_iterator + +#if !defined(__cpp_lib_null_iterators) +# if (__cplusplus >= 201402L) +# define __glibcxx_null_iterators 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_null_iterators) +# define __cpp_lib_null_iterators 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_null_iterators) && defined(__glibcxx_want_null_iterators) */ +#undef __glibcxx_want_null_iterators + +#if !defined(__cpp_lib_transformation_trait_aliases) +# if (__cplusplus >= 201402L) +# define __glibcxx_transformation_trait_aliases 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_transformation_trait_aliases) +# define __cpp_lib_transformation_trait_aliases 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_transformation_trait_aliases) && defined(__glibcxx_want_transformation_trait_aliases) */ +#undef __glibcxx_want_transformation_trait_aliases + +#if !defined(__cpp_lib_transparent_operators) +# if (__cplusplus >= 201402L) +# define __glibcxx_transparent_operators 201510L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_transparent_operators) +# define __cpp_lib_transparent_operators 201510L +# endif +# endif +#endif /* !defined(__cpp_lib_transparent_operators) && defined(__glibcxx_want_transparent_operators) */ +#undef __glibcxx_want_transparent_operators + +#if !defined(__cpp_lib_tuple_element_t) +# if (__cplusplus >= 201402L) +# define __glibcxx_tuple_element_t 201402L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_tuple_element_t) +# define __cpp_lib_tuple_element_t 201402L +# endif +# endif +#endif /* !defined(__cpp_lib_tuple_element_t) && defined(__glibcxx_want_tuple_element_t) */ +#undef __glibcxx_want_tuple_element_t + +#if !defined(__cpp_lib_tuples_by_type) +# if (__cplusplus >= 201402L) +# define __glibcxx_tuples_by_type 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_tuples_by_type) +# define __cpp_lib_tuples_by_type 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_tuples_by_type) && defined(__glibcxx_want_tuples_by_type) */ +#undef __glibcxx_want_tuples_by_type + +#if !defined(__cpp_lib_robust_nonmodifying_seq_ops) +# if (__cplusplus >= 201402L) +# define __glibcxx_robust_nonmodifying_seq_ops 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_robust_nonmodifying_seq_ops) +# define __cpp_lib_robust_nonmodifying_seq_ops 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_robust_nonmodifying_seq_ops) && defined(__glibcxx_want_robust_nonmodifying_seq_ops) */ +#undef __glibcxx_want_robust_nonmodifying_seq_ops + +#if !defined(__cpp_lib_to_chars) +# if (__cplusplus > 202302L) && (_GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && __SIZE_WIDTH__ >= 32) +# define __glibcxx_to_chars 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_chars) +# define __cpp_lib_to_chars 202306L +# endif +# elif (__cplusplus >= 201402L) && (_GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && __SIZE_WIDTH__ >= 32) +# define __glibcxx_to_chars 201611L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_chars) +# define __cpp_lib_to_chars 201611L +# endif +# endif +#endif /* !defined(__cpp_lib_to_chars) && defined(__glibcxx_want_to_chars) */ +#undef __glibcxx_want_to_chars + +#if !defined(__cpp_lib_chrono_udls) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_chrono_udls 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_udls) +# define __cpp_lib_chrono_udls 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_chrono_udls) && defined(__glibcxx_want_chrono_udls) */ +#undef __glibcxx_want_chrono_udls + +#if !defined(__cpp_lib_complex_udls) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_complex_udls 201309L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_complex_udls) +# define __cpp_lib_complex_udls 201309L +# endif +# endif +#endif /* !defined(__cpp_lib_complex_udls) && defined(__glibcxx_want_complex_udls) */ +#undef __glibcxx_want_complex_udls + +#if !defined(__cpp_lib_generic_associative_lookup) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_generic_associative_lookup 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_generic_associative_lookup) +# define __cpp_lib_generic_associative_lookup 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_generic_associative_lookup) && defined(__glibcxx_want_generic_associative_lookup) */ +#undef __glibcxx_want_generic_associative_lookup + +#if !defined(__cpp_lib_make_unique) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_make_unique 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_unique) +# define __cpp_lib_make_unique 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_make_unique) && defined(__glibcxx_want_make_unique) */ +#undef __glibcxx_want_make_unique + +#if !defined(__cpp_lib_quoted_string_io) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_quoted_string_io 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_quoted_string_io) +# define __cpp_lib_quoted_string_io 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_quoted_string_io) && defined(__glibcxx_want_quoted_string_io) */ +#undef __glibcxx_want_quoted_string_io + +#if !defined(__cpp_lib_shared_timed_mutex) +# if (__cplusplus >= 201402L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_shared_timed_mutex 201402L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shared_timed_mutex) +# define __cpp_lib_shared_timed_mutex 201402L +# endif +# endif +#endif /* !defined(__cpp_lib_shared_timed_mutex) && defined(__glibcxx_want_shared_timed_mutex) */ +#undef __glibcxx_want_shared_timed_mutex + +#if !defined(__cpp_lib_string_udls) +# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED +# define __glibcxx_string_udls 201304L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_udls) +# define __cpp_lib_string_udls 201304L +# endif +# endif +#endif /* !defined(__cpp_lib_string_udls) && defined(__glibcxx_want_string_udls) */ +#undef __glibcxx_want_string_udls + +#if !defined(__cpp_lib_addressof_constexpr) +# if (__cplusplus >= 201703L) +# define __glibcxx_addressof_constexpr 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_addressof_constexpr) +# define __cpp_lib_addressof_constexpr 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_addressof_constexpr) && defined(__glibcxx_want_addressof_constexpr) */ +#undef __glibcxx_want_addressof_constexpr + +#if !defined(__cpp_lib_any) +# if (__cplusplus >= 201703L) +# define __glibcxx_any 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_any) +# define __cpp_lib_any 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_any) && defined(__glibcxx_want_any) */ +#undef __glibcxx_want_any + +#if !defined(__cpp_lib_apply) +# if (__cplusplus >= 201703L) +# define __glibcxx_apply 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_apply) +# define __cpp_lib_apply 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_apply) && defined(__glibcxx_want_apply) */ +#undef __glibcxx_want_apply + +#if !defined(__cpp_lib_as_const) +# if (__cplusplus >= 201703L) +# define __glibcxx_as_const 201510L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_as_const) +# define __cpp_lib_as_const 201510L +# endif +# endif +#endif /* !defined(__cpp_lib_as_const) && defined(__glibcxx_want_as_const) */ +#undef __glibcxx_want_as_const + +#if !defined(__cpp_lib_atomic_is_always_lock_free) +# if (__cplusplus >= 201703L) +# define __glibcxx_atomic_is_always_lock_free 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_is_always_lock_free) +# define __cpp_lib_atomic_is_always_lock_free 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_is_always_lock_free) && defined(__glibcxx_want_atomic_is_always_lock_free) */ +#undef __glibcxx_want_atomic_is_always_lock_free + +#if !defined(__cpp_lib_bool_constant) +# if (__cplusplus >= 201703L) +# define __glibcxx_bool_constant 201505L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bool_constant) +# define __cpp_lib_bool_constant 201505L +# endif +# endif +#endif /* !defined(__cpp_lib_bool_constant) && defined(__glibcxx_want_bool_constant) */ +#undef __glibcxx_want_bool_constant + +#if !defined(__cpp_lib_byte) +# if (__cplusplus >= 201703L) +# define __glibcxx_byte 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_byte) +# define __cpp_lib_byte 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_byte) && defined(__glibcxx_want_byte) */ +#undef __glibcxx_want_byte + +#if !defined(__cpp_lib_has_unique_object_representations) +# if (__cplusplus >= 201703L) && (defined(_GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP)) +# define __glibcxx_has_unique_object_representations 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_has_unique_object_representations) +# define __cpp_lib_has_unique_object_representations 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_has_unique_object_representations) && defined(__glibcxx_want_has_unique_object_representations) */ +#undef __glibcxx_want_has_unique_object_representations + +#if !defined(__cpp_lib_hardware_interference_size) +# if (__cplusplus >= 201703L) && (defined(__GCC_DESTRUCTIVE_SIZE)) +# define __glibcxx_hardware_interference_size 201703L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_hardware_interference_size) +# define __cpp_lib_hardware_interference_size 201703L +# endif +# endif +#endif /* !defined(__cpp_lib_hardware_interference_size) && defined(__glibcxx_want_hardware_interference_size) */ +#undef __glibcxx_want_hardware_interference_size + +#if !defined(__cpp_lib_invoke) +# if (__cplusplus >= 201703L) +# define __glibcxx_invoke 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_invoke) +# define __cpp_lib_invoke 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_invoke) && defined(__glibcxx_want_invoke) */ +#undef __glibcxx_want_invoke + +#if !defined(__cpp_lib_is_aggregate) +# if (__cplusplus >= 201703L) && (defined(_GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE)) +# define __glibcxx_is_aggregate 201703L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_aggregate) +# define __cpp_lib_is_aggregate 201703L +# endif +# endif +#endif /* !defined(__cpp_lib_is_aggregate) && defined(__glibcxx_want_is_aggregate) */ +#undef __glibcxx_want_is_aggregate + +#if !defined(__cpp_lib_is_invocable) +# if (__cplusplus >= 201703L) +# define __glibcxx_is_invocable 201703L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_invocable) +# define __cpp_lib_is_invocable 201703L +# endif +# endif +#endif /* !defined(__cpp_lib_is_invocable) && defined(__glibcxx_want_is_invocable) */ +#undef __glibcxx_want_is_invocable + +#if !defined(__cpp_lib_launder) +# if (__cplusplus >= 201703L) && (defined(_GLIBCXX_HAVE_BUILTIN_LAUNDER)) +# define __glibcxx_launder 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_launder) +# define __cpp_lib_launder 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_launder) && defined(__glibcxx_want_launder) */ +#undef __glibcxx_want_launder + +#if !defined(__cpp_lib_logical_traits) +# if (__cplusplus >= 201703L) +# define __glibcxx_logical_traits 201510L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_logical_traits) +# define __cpp_lib_logical_traits 201510L +# endif +# endif +#endif /* !defined(__cpp_lib_logical_traits) && defined(__glibcxx_want_logical_traits) */ +#undef __glibcxx_want_logical_traits + +#if !defined(__cpp_lib_make_from_tuple) +# if (__cplusplus >= 201703L) +# define __glibcxx_make_from_tuple 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_from_tuple) +# define __cpp_lib_make_from_tuple 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_make_from_tuple) && defined(__glibcxx_want_make_from_tuple) */ +#undef __glibcxx_want_make_from_tuple + +#if !defined(__cpp_lib_not_fn) +# if (__cplusplus >= 201703L) +# define __glibcxx_not_fn 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn) +# define __cpp_lib_not_fn 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_not_fn) && defined(__glibcxx_want_not_fn) */ +#undef __glibcxx_want_not_fn + +#if !defined(__cpp_lib_type_trait_variable_templates) +# if (__cplusplus >= 201703L) +# define __glibcxx_type_trait_variable_templates 201510L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_type_trait_variable_templates) +# define __cpp_lib_type_trait_variable_templates 201510L +# endif +# endif +#endif /* !defined(__cpp_lib_type_trait_variable_templates) && defined(__glibcxx_want_type_trait_variable_templates) */ +#undef __glibcxx_want_type_trait_variable_templates + +#if !defined(__cpp_lib_variant) +# if (__cplusplus >= 202002L) && (__cpp_concepts >= 202002L && __cpp_constexpr >= 201811L) +# define __glibcxx_variant 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_variant) +# define __cpp_lib_variant 202106L +# endif +# elif (__cplusplus >= 201703L) +# define __glibcxx_variant 202102L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_variant) +# define __cpp_lib_variant 202102L +# endif +# endif +#endif /* !defined(__cpp_lib_variant) && defined(__glibcxx_want_variant) */ +#undef __glibcxx_want_variant + +#if !defined(__cpp_lib_lcm) +# if (__cplusplus >= 201703L) +# define __glibcxx_lcm 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_lcm) +# define __cpp_lib_lcm 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_lcm) && defined(__glibcxx_want_lcm) */ +#undef __glibcxx_want_lcm + +#if !defined(__cpp_lib_gcd) +# if (__cplusplus >= 201703L) +# define __glibcxx_gcd 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_gcd) +# define __cpp_lib_gcd 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_gcd) && defined(__glibcxx_want_gcd) */ +#undef __glibcxx_want_gcd + +#if !defined(__cpp_lib_gcd_lcm) +# if (__cplusplus >= 201703L) +# define __glibcxx_gcd_lcm 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_gcd_lcm) +# define __cpp_lib_gcd_lcm 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_gcd_lcm) && defined(__glibcxx_want_gcd_lcm) */ +#undef __glibcxx_want_gcd_lcm + +#if !defined(__cpp_lib_raw_memory_algorithms) +# if (__cplusplus >= 201703L) +# define __glibcxx_raw_memory_algorithms 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_raw_memory_algorithms) +# define __cpp_lib_raw_memory_algorithms 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_raw_memory_algorithms) && defined(__glibcxx_want_raw_memory_algorithms) */ +#undef __glibcxx_want_raw_memory_algorithms + +#if !defined(__cpp_lib_array_constexpr) +# if (__cplusplus >= 202002L) +# define __glibcxx_array_constexpr 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_array_constexpr) +# define __cpp_lib_array_constexpr 201811L +# endif +# elif (__cplusplus >= 201703L) +# define __glibcxx_array_constexpr 201803L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_array_constexpr) +# define __cpp_lib_array_constexpr 201803L +# endif +# endif +#endif /* !defined(__cpp_lib_array_constexpr) && defined(__glibcxx_want_array_constexpr) */ +#undef __glibcxx_want_array_constexpr + +#if !defined(__cpp_lib_nonmember_container_access) +# if (__cplusplus >= 201703L) +# define __glibcxx_nonmember_container_access 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_nonmember_container_access) +# define __cpp_lib_nonmember_container_access 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_nonmember_container_access) && defined(__glibcxx_want_nonmember_container_access) */ +#undef __glibcxx_want_nonmember_container_access + +#if !defined(__cpp_lib_clamp) +# if (__cplusplus >= 201703L) +# define __glibcxx_clamp 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_clamp) +# define __cpp_lib_clamp 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_clamp) && defined(__glibcxx_want_clamp) */ +#undef __glibcxx_want_clamp + +#if !defined(__cpp_lib_sample) +# if (__cplusplus >= 201703L) +# define __glibcxx_sample 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_sample) +# define __cpp_lib_sample 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_sample) && defined(__glibcxx_want_sample) */ +#undef __glibcxx_want_sample + +#if !defined(__cpp_lib_boyer_moore_searcher) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_boyer_moore_searcher 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_boyer_moore_searcher) +# define __cpp_lib_boyer_moore_searcher 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_boyer_moore_searcher) && defined(__glibcxx_want_boyer_moore_searcher) */ +#undef __glibcxx_want_boyer_moore_searcher + +#if !defined(__cpp_lib_chrono) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_chrono 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono) +# define __cpp_lib_chrono 201907L +# endif +# elif (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_chrono 201611L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono) +# define __cpp_lib_chrono 201611L +# endif +# endif +#endif /* !defined(__cpp_lib_chrono) && defined(__glibcxx_want_chrono) */ +#undef __glibcxx_want_chrono + +#if !defined(__cpp_lib_execution) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_execution 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_execution) +# define __cpp_lib_execution 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_execution) && defined(__glibcxx_want_execution) */ +#undef __glibcxx_want_execution + +#if !defined(__cpp_lib_filesystem) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_filesystem 201703L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_filesystem) +# define __cpp_lib_filesystem 201703L +# endif +# endif +#endif /* !defined(__cpp_lib_filesystem) && defined(__glibcxx_want_filesystem) */ +#undef __glibcxx_want_filesystem + +#if !defined(__cpp_lib_hypot) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_hypot 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_hypot) +# define __cpp_lib_hypot 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_hypot) && defined(__glibcxx_want_hypot) */ +#undef __glibcxx_want_hypot + +#if !defined(__cpp_lib_map_try_emplace) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_map_try_emplace 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_map_try_emplace) +# define __cpp_lib_map_try_emplace 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_map_try_emplace) && defined(__glibcxx_want_map_try_emplace) */ +#undef __glibcxx_want_map_try_emplace + +#if !defined(__cpp_lib_math_special_functions) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_math_special_functions 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_math_special_functions) +# define __cpp_lib_math_special_functions 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_math_special_functions) && defined(__glibcxx_want_math_special_functions) */ +#undef __glibcxx_want_math_special_functions + +#if !defined(__cpp_lib_memory_resource) +# if (__cplusplus >= 201703L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_memory_resource 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_memory_resource) +# define __cpp_lib_memory_resource 201603L +# endif +# elif (__cplusplus >= 201703L) && !defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_memory_resource 1L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_memory_resource) +# define __cpp_lib_memory_resource 1L +# endif +# endif +#endif /* !defined(__cpp_lib_memory_resource) && defined(__glibcxx_want_memory_resource) */ +#undef __glibcxx_want_memory_resource + +#if !defined(__cpp_lib_node_extract) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_node_extract 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_node_extract) +# define __cpp_lib_node_extract 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_node_extract) && defined(__glibcxx_want_node_extract) */ +#undef __glibcxx_want_node_extract + +#if !defined(__cpp_lib_parallel_algorithm) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_parallel_algorithm 201603L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_parallel_algorithm) +# define __cpp_lib_parallel_algorithm 201603L +# endif +# endif +#endif /* !defined(__cpp_lib_parallel_algorithm) && defined(__glibcxx_want_parallel_algorithm) */ +#undef __glibcxx_want_parallel_algorithm + +#if !defined(__cpp_lib_scoped_lock) +# if (__cplusplus >= 201703L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_scoped_lock 201703L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_scoped_lock) +# define __cpp_lib_scoped_lock 201703L +# endif +# endif +#endif /* !defined(__cpp_lib_scoped_lock) && defined(__glibcxx_want_scoped_lock) */ +#undef __glibcxx_want_scoped_lock + +#if !defined(__cpp_lib_shared_mutex) +# if (__cplusplus >= 201703L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_shared_mutex 201505L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shared_mutex) +# define __cpp_lib_shared_mutex 201505L +# endif +# endif +#endif /* !defined(__cpp_lib_shared_mutex) && defined(__glibcxx_want_shared_mutex) */ +#undef __glibcxx_want_shared_mutex + +#if !defined(__cpp_lib_shared_ptr_weak_type) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_shared_ptr_weak_type 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shared_ptr_weak_type) +# define __cpp_lib_shared_ptr_weak_type 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_shared_ptr_weak_type) && defined(__glibcxx_want_shared_ptr_weak_type) */ +#undef __glibcxx_want_shared_ptr_weak_type + +#if !defined(__cpp_lib_string_view) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_string_view 201803L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_view) +# define __cpp_lib_string_view 201803L +# endif +# endif +#endif /* !defined(__cpp_lib_string_view) && defined(__glibcxx_want_string_view) */ +#undef __glibcxx_want_string_view + +#if !defined(__cpp_lib_unordered_map_try_emplace) +# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED +# define __glibcxx_unordered_map_try_emplace 201411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unordered_map_try_emplace) +# define __cpp_lib_unordered_map_try_emplace 201411L +# endif +# endif +#endif /* !defined(__cpp_lib_unordered_map_try_emplace) && defined(__glibcxx_want_unordered_map_try_emplace) */ +#undef __glibcxx_want_unordered_map_try_emplace + +#if !defined(__cpp_lib_assume_aligned) +# if (__cplusplus >= 202002L) +# define __glibcxx_assume_aligned 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_assume_aligned) +# define __cpp_lib_assume_aligned 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_assume_aligned) && defined(__glibcxx_want_assume_aligned) */ +#undef __glibcxx_want_assume_aligned + +#if !defined(__cpp_lib_atomic_flag_test) +# if (__cplusplus >= 202002L) +# define __glibcxx_atomic_flag_test 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_flag_test) +# define __cpp_lib_atomic_flag_test 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_flag_test) && defined(__glibcxx_want_atomic_flag_test) */ +#undef __glibcxx_want_atomic_flag_test + +#if !defined(__cpp_lib_atomic_float) +# if (__cplusplus >= 202002L) +# define __glibcxx_atomic_float 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_float) +# define __cpp_lib_atomic_float 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_float) && defined(__glibcxx_want_atomic_float) */ +#undef __glibcxx_want_atomic_float + +#if !defined(__cpp_lib_atomic_lock_free_type_aliases) +# if (__cplusplus >= 202002L) && ((__GCC_ATOMIC_INT_LOCK_FREE | __GCC_ATOMIC_LONG_LOCK_FREE | __GCC_ATOMIC_CHAR_LOCK_FREE) & 2) +# define __glibcxx_atomic_lock_free_type_aliases 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_lock_free_type_aliases) +# define __cpp_lib_atomic_lock_free_type_aliases 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_lock_free_type_aliases) && defined(__glibcxx_want_atomic_lock_free_type_aliases) */ +#undef __glibcxx_want_atomic_lock_free_type_aliases + +#if !defined(__cpp_lib_atomic_ref) +# if (__cplusplus >= 202002L) +# define __glibcxx_atomic_ref 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_ref) +# define __cpp_lib_atomic_ref 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_ref) && defined(__glibcxx_want_atomic_ref) */ +#undef __glibcxx_want_atomic_ref + +#if !defined(__cpp_lib_atomic_value_initialization) +# if (__cplusplus >= 202002L) +# define __glibcxx_atomic_value_initialization 201911L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_value_initialization) +# define __cpp_lib_atomic_value_initialization 201911L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_value_initialization) && defined(__glibcxx_want_atomic_value_initialization) */ +#undef __glibcxx_want_atomic_value_initialization + +#if !defined(__cpp_lib_bind_front) +# if (__cplusplus >= 202002L) +# define __glibcxx_bind_front 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front) +# define __cpp_lib_bind_front 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_bind_front) && defined(__glibcxx_want_bind_front) */ +#undef __glibcxx_want_bind_front + +#if !defined(__cpp_lib_bind_back) +# if (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter) +# define __glibcxx_bind_back 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back) +# define __cpp_lib_bind_back 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_bind_back) && defined(__glibcxx_want_bind_back) */ +#undef __glibcxx_want_bind_back + +#if !defined(__cpp_lib_starts_ends_with) +# if (__cplusplus >= 202002L) +# define __glibcxx_starts_ends_with 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_starts_ends_with) +# define __cpp_lib_starts_ends_with 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_starts_ends_with) && defined(__glibcxx_want_starts_ends_with) */ +#undef __glibcxx_want_starts_ends_with + +#if !defined(__cpp_lib_bit_cast) +# if (__cplusplus >= 202002L) && (__has_builtin(__builtin_bit_cast)) +# define __glibcxx_bit_cast 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bit_cast) +# define __cpp_lib_bit_cast 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_bit_cast) && defined(__glibcxx_want_bit_cast) */ +#undef __glibcxx_want_bit_cast + +#if !defined(__cpp_lib_bitops) +# if (__cplusplus >= 202002L) +# define __glibcxx_bitops 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitops) +# define __cpp_lib_bitops 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_bitops) && defined(__glibcxx_want_bitops) */ +#undef __glibcxx_want_bitops + +#if !defined(__cpp_lib_bounded_array_traits) +# if (__cplusplus >= 202002L) +# define __glibcxx_bounded_array_traits 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bounded_array_traits) +# define __cpp_lib_bounded_array_traits 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_bounded_array_traits) && defined(__glibcxx_want_bounded_array_traits) */ +#undef __glibcxx_want_bounded_array_traits + +#if !defined(__cpp_lib_concepts) +# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L) +# define __glibcxx_concepts 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts) +# define __cpp_lib_concepts 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_concepts) && defined(__glibcxx_want_concepts) */ +#undef __glibcxx_want_concepts + +#if !defined(__cpp_lib_optional) +# if (__cplusplus >= 202100L) && (__glibcxx_concepts) +# define __glibcxx_optional 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional) +# define __cpp_lib_optional 202110L +# endif +# elif (__cplusplus >= 202002L) +# define __glibcxx_optional 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional) +# define __cpp_lib_optional 202106L +# endif +# elif (__cplusplus >= 201703L) +# define __glibcxx_optional 201606L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional) +# define __cpp_lib_optional 201606L +# endif +# endif +#endif /* !defined(__cpp_lib_optional) && defined(__glibcxx_want_optional) */ +#undef __glibcxx_want_optional + +#if !defined(__cpp_lib_destroying_delete) +# if (__cplusplus >= 202002L) && (__cpp_impl_destroying_delete) +# define __glibcxx_destroying_delete 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_destroying_delete) +# define __cpp_lib_destroying_delete 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_destroying_delete) && defined(__glibcxx_want_destroying_delete) */ +#undef __glibcxx_want_destroying_delete + +#if !defined(__cpp_lib_constexpr_string_view) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_string_view 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_string_view) +# define __cpp_lib_constexpr_string_view 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_string_view) && defined(__glibcxx_want_constexpr_string_view) */ +#undef __glibcxx_want_constexpr_string_view + +#if !defined(__cpp_lib_endian) +# if (__cplusplus >= 202002L) +# define __glibcxx_endian 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_endian) +# define __cpp_lib_endian 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_endian) && defined(__glibcxx_want_endian) */ +#undef __glibcxx_want_endian + +#if !defined(__cpp_lib_int_pow2) +# if (__cplusplus >= 202002L) +# define __glibcxx_int_pow2 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_int_pow2) +# define __cpp_lib_int_pow2 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_int_pow2) && defined(__glibcxx_want_int_pow2) */ +#undef __glibcxx_want_int_pow2 + +#if !defined(__cpp_lib_integer_comparison_functions) +# if (__cplusplus >= 202002L) +# define __glibcxx_integer_comparison_functions 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_integer_comparison_functions) +# define __cpp_lib_integer_comparison_functions 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_integer_comparison_functions) && defined(__glibcxx_want_integer_comparison_functions) */ +#undef __glibcxx_want_integer_comparison_functions + +#if !defined(__cpp_lib_is_constant_evaluated) +# if (__cplusplus >= 202002L) && (defined(_GLIBCXX_HAVE_IS_CONSTANT_EVALUATED)) +# define __glibcxx_is_constant_evaluated 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_constant_evaluated) +# define __cpp_lib_is_constant_evaluated 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_is_constant_evaluated) && defined(__glibcxx_want_is_constant_evaluated) */ +#undef __glibcxx_want_is_constant_evaluated + +#if !defined(__cpp_lib_constexpr_char_traits) +# if (__cplusplus >= 202002L) && (defined(__glibcxx_is_constant_evaluated)) +# define __glibcxx_constexpr_char_traits 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_char_traits) +# define __cpp_lib_constexpr_char_traits 201811L +# endif +# elif (__cplusplus >= 201703L) && (_GLIBCXX_HAVE_IS_CONSTANT_EVALUATED) +# define __glibcxx_constexpr_char_traits 201611L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_char_traits) +# define __cpp_lib_constexpr_char_traits 201611L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_char_traits) && defined(__glibcxx_want_constexpr_char_traits) */ +#undef __glibcxx_want_constexpr_char_traits + +#if !defined(__cpp_lib_is_layout_compatible) +# if (__cplusplus >= 202002L) && (__has_builtin(__is_layout_compatible) && __has_builtin(__builtin_is_corresponding_member)) +# define __glibcxx_is_layout_compatible 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_layout_compatible) +# define __cpp_lib_is_layout_compatible 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_is_layout_compatible) && defined(__glibcxx_want_is_layout_compatible) */ +#undef __glibcxx_want_is_layout_compatible + +#if !defined(__cpp_lib_is_nothrow_convertible) +# if (__cplusplus >= 202002L) +# define __glibcxx_is_nothrow_convertible 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_nothrow_convertible) +# define __cpp_lib_is_nothrow_convertible 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_is_nothrow_convertible) && defined(__glibcxx_want_is_nothrow_convertible) */ +#undef __glibcxx_want_is_nothrow_convertible + +#if !defined(__cpp_lib_is_pointer_interconvertible) +# if (__cplusplus >= 202002L) && (__has_builtin(__is_pointer_interconvertible_base_of) && __has_builtin(__builtin_is_pointer_interconvertible_with_class)) +# define __glibcxx_is_pointer_interconvertible 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_pointer_interconvertible) +# define __cpp_lib_is_pointer_interconvertible 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_is_pointer_interconvertible) && defined(__glibcxx_want_is_pointer_interconvertible) */ +#undef __glibcxx_want_is_pointer_interconvertible + +#if !defined(__cpp_lib_math_constants) +# if (__cplusplus >= 202002L) +# define __glibcxx_math_constants 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_math_constants) +# define __cpp_lib_math_constants 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_math_constants) && defined(__glibcxx_want_math_constants) */ +#undef __glibcxx_want_math_constants + +#if !defined(__cpp_lib_make_obj_using_allocator) +# if (__cplusplus >= 202002L) && (__cpp_concepts) +# define __glibcxx_make_obj_using_allocator 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_obj_using_allocator) +# define __cpp_lib_make_obj_using_allocator 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_make_obj_using_allocator) && defined(__glibcxx_want_make_obj_using_allocator) */ +#undef __glibcxx_want_make_obj_using_allocator + +#if !defined(__cpp_lib_remove_cvref) +# if (__cplusplus >= 202002L) +# define __glibcxx_remove_cvref 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_remove_cvref) +# define __cpp_lib_remove_cvref 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_remove_cvref) && defined(__glibcxx_want_remove_cvref) */ +#undef __glibcxx_want_remove_cvref + +#if !defined(__cpp_lib_source_location) +# if (__cplusplus >= 202002L) && (__has_builtin(__builtin_source_location)) +# define __glibcxx_source_location 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_source_location) +# define __cpp_lib_source_location 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_source_location) && defined(__glibcxx_want_source_location) */ +#undef __glibcxx_want_source_location + +#if !defined(__cpp_lib_span) +# if (__cplusplus > 202302L) && (__glibcxx_concepts) +# define __glibcxx_span 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_span) +# define __cpp_lib_span 202311L +# endif +# elif (__cplusplus >= 202002L) && (__glibcxx_concepts) +# define __glibcxx_span 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_span) +# define __cpp_lib_span 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_span) && defined(__glibcxx_want_span) */ +#undef __glibcxx_want_span + +#if !defined(__cpp_lib_ssize) +# if (__cplusplus >= 202002L) +# define __glibcxx_ssize 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ssize) +# define __cpp_lib_ssize 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_ssize) && defined(__glibcxx_want_ssize) */ +#undef __glibcxx_want_ssize + +#if !defined(__cpp_lib_three_way_comparison) +# if (__cplusplus >= 202002L) && (__cpp_impl_three_way_comparison >= 201907L && __glibcxx_concepts) +# define __glibcxx_three_way_comparison 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_three_way_comparison) +# define __cpp_lib_three_way_comparison 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_three_way_comparison) && defined(__glibcxx_want_three_way_comparison) */ +#undef __glibcxx_want_three_way_comparison + +#if !defined(__cpp_lib_to_address) +# if (__cplusplus >= 202002L) +# define __glibcxx_to_address 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_address) +# define __cpp_lib_to_address 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_to_address) && defined(__glibcxx_want_to_address) */ +#undef __glibcxx_want_to_address + +#if !defined(__cpp_lib_to_array) +# if (__cplusplus >= 202002L) && (__cpp_generic_lambdas >= 201707L) +# define __glibcxx_to_array 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_array) +# define __cpp_lib_to_array 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_to_array) && defined(__glibcxx_want_to_array) */ +#undef __glibcxx_want_to_array + +#if !defined(__cpp_lib_type_identity) +# if (__cplusplus >= 202002L) +# define __glibcxx_type_identity 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_type_identity) +# define __cpp_lib_type_identity 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_type_identity) && defined(__glibcxx_want_type_identity) */ +#undef __glibcxx_want_type_identity + +#if !defined(__cpp_lib_unwrap_ref) +# if (__cplusplus >= 202002L) +# define __glibcxx_unwrap_ref 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unwrap_ref) +# define __cpp_lib_unwrap_ref 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_unwrap_ref) && defined(__glibcxx_want_unwrap_ref) */ +#undef __glibcxx_want_unwrap_ref + +#if !defined(__cpp_lib_constexpr_iterator) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_iterator 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_iterator) +# define __cpp_lib_constexpr_iterator 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_iterator) && defined(__glibcxx_want_constexpr_iterator) */ +#undef __glibcxx_want_constexpr_iterator + +#if !defined(__cpp_lib_interpolate) +# if (__cplusplus >= 202002L) +# define __glibcxx_interpolate 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_interpolate) +# define __cpp_lib_interpolate 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_interpolate) && defined(__glibcxx_want_interpolate) */ +#undef __glibcxx_want_interpolate + +#if !defined(__cpp_lib_constexpr_utility) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_utility 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_utility) +# define __cpp_lib_constexpr_utility 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_utility) && defined(__glibcxx_want_constexpr_utility) */ +#undef __glibcxx_want_constexpr_utility + +#if !defined(__cpp_lib_shift) +# if (__cplusplus >= 202002L) +# define __glibcxx_shift 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift) +# define __cpp_lib_shift 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_shift) && defined(__glibcxx_want_shift) */ +#undef __glibcxx_want_shift + +#if !defined(__cpp_lib_ranges) +# if (__cplusplus >= 202100L) && (__glibcxx_concepts) +# define __glibcxx_ranges 202211L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges) +# define __cpp_lib_ranges 202211L +# endif +# elif (__cplusplus >= 202002L) && (__glibcxx_concepts) +# define __glibcxx_ranges 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges) +# define __cpp_lib_ranges 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges) && defined(__glibcxx_want_ranges) */ +#undef __glibcxx_want_ranges + +#if !defined(__cpp_lib_constexpr_numeric) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_numeric 201911L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_numeric) +# define __cpp_lib_constexpr_numeric 201911L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_numeric) && defined(__glibcxx_want_constexpr_numeric) */ +#undef __glibcxx_want_constexpr_numeric + +#if !defined(__cpp_lib_constexpr_functional) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_functional 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_functional) +# define __cpp_lib_constexpr_functional 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_functional) && defined(__glibcxx_want_constexpr_functional) */ +#undef __glibcxx_want_constexpr_functional + +#if !defined(__cpp_lib_constexpr_algorithms) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_algorithms 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_algorithms) +# define __cpp_lib_constexpr_algorithms 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_algorithms) && defined(__glibcxx_want_constexpr_algorithms) */ +#undef __glibcxx_want_constexpr_algorithms + +#if !defined(__cpp_lib_constexpr_tuple) +# if (__cplusplus >= 202002L) +# define __glibcxx_constexpr_tuple 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_tuple) +# define __cpp_lib_constexpr_tuple 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_tuple) && defined(__glibcxx_want_constexpr_tuple) */ +#undef __glibcxx_want_constexpr_tuple + +#if !defined(__cpp_lib_constexpr_memory) +# if (__cplusplus >= 202100L) && (__cpp_constexpr_dynamic_alloc) +# define __glibcxx_constexpr_memory 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_memory) +# define __cpp_lib_constexpr_memory 202202L +# endif +# elif (__cplusplus >= 202002L) +# define __glibcxx_constexpr_memory 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_memory) +# define __cpp_lib_constexpr_memory 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_memory) && defined(__glibcxx_want_constexpr_memory) */ +#undef __glibcxx_want_constexpr_memory + +#if !defined(__cpp_lib_atomic_shared_ptr) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_atomic_shared_ptr 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_shared_ptr) +# define __cpp_lib_atomic_shared_ptr 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_shared_ptr) && defined(__glibcxx_want_atomic_shared_ptr) */ +#undef __glibcxx_want_atomic_shared_ptr + +#if !defined(__cpp_lib_atomic_wait) +# if (__cplusplus >= 202002L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_atomic_wait 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_wait) +# define __cpp_lib_atomic_wait 201907L +# endif +# elif (__cplusplus >= 202002L) && !defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED && (defined(_GLIBCXX_HAVE_LINUX_FUTEX)) +# define __glibcxx_atomic_wait 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_wait) +# define __cpp_lib_atomic_wait 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_atomic_wait) && defined(__glibcxx_want_atomic_wait) */ +#undef __glibcxx_want_atomic_wait + +#if !defined(__cpp_lib_barrier) +# if (__cplusplus >= 202002L) && (__cpp_aligned_new && __glibcxx_atomic_wait) +# define __glibcxx_barrier 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_barrier) +# define __cpp_lib_barrier 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_barrier) && defined(__glibcxx_want_barrier) */ +#undef __glibcxx_want_barrier + +#if !defined(__cpp_lib_format) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_format 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format) +# define __cpp_lib_format 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_format) && defined(__glibcxx_want_format) */ +#undef __glibcxx_want_format + +#if !defined(__cpp_lib_format_uchar) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_format_uchar 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_uchar) +# define __cpp_lib_format_uchar 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_format_uchar) && defined(__glibcxx_want_format_uchar) */ +#undef __glibcxx_want_format_uchar + +#if !defined(__cpp_lib_constexpr_complex) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_constexpr_complex 201711L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_complex) +# define __cpp_lib_constexpr_complex 201711L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_complex) && defined(__glibcxx_want_constexpr_complex) */ +#undef __glibcxx_want_constexpr_complex + +#if !defined(__cpp_lib_constexpr_dynamic_alloc) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_constexpr_dynamic_alloc 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_dynamic_alloc) +# define __cpp_lib_constexpr_dynamic_alloc 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) && defined(__glibcxx_want_constexpr_dynamic_alloc) */ +#undef __glibcxx_want_constexpr_dynamic_alloc + +#if !defined(__cpp_lib_constexpr_string) +# if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED && (defined(__glibcxx_is_constant_evaluated)) +# define __glibcxx_constexpr_string 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_string) +# define __cpp_lib_constexpr_string 201907L +# endif +# elif (__cplusplus >= 202002L) && !_GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED && (defined(__glibcxx_is_constant_evaluated)) +# define __glibcxx_constexpr_string 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_string) +# define __cpp_lib_constexpr_string 201811L +# endif +# elif (__cplusplus >= 201703L) && _GLIBCXX_HOSTED && (_GLIBCXX_HAVE_IS_CONSTANT_EVALUATED) +# define __glibcxx_constexpr_string 201611L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_string) +# define __cpp_lib_constexpr_string 201611L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_string) && defined(__glibcxx_want_constexpr_string) */ +#undef __glibcxx_want_constexpr_string + +#if !defined(__cpp_lib_constexpr_vector) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_constexpr_vector 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_vector) +# define __cpp_lib_constexpr_vector 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_vector) && defined(__glibcxx_want_constexpr_vector) */ +#undef __glibcxx_want_constexpr_vector + +#if !defined(__cpp_lib_erase_if) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_erase_if 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_erase_if) +# define __cpp_lib_erase_if 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_erase_if) && defined(__glibcxx_want_erase_if) */ +#undef __glibcxx_want_erase_if + +#if !defined(__cpp_lib_generic_unordered_lookup) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_generic_unordered_lookup 201811L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_generic_unordered_lookup) +# define __cpp_lib_generic_unordered_lookup 201811L +# endif +# endif +#endif /* !defined(__cpp_lib_generic_unordered_lookup) && defined(__glibcxx_want_generic_unordered_lookup) */ +#undef __glibcxx_want_generic_unordered_lookup + +#if !defined(__cpp_lib_jthread) +# if (__cplusplus >= 202002L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED +# define __glibcxx_jthread 201911L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_jthread) +# define __cpp_lib_jthread 201911L +# endif +# endif +#endif /* !defined(__cpp_lib_jthread) && defined(__glibcxx_want_jthread) */ +#undef __glibcxx_want_jthread + +#if !defined(__cpp_lib_latch) +# if (__cplusplus >= 202002L) && (__glibcxx_atomic_wait) +# define __glibcxx_latch 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_latch) +# define __cpp_lib_latch 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_latch) && defined(__glibcxx_want_latch) */ +#undef __glibcxx_want_latch + +#if !defined(__cpp_lib_list_remove_return_type) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_list_remove_return_type 201806L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_list_remove_return_type) +# define __cpp_lib_list_remove_return_type 201806L +# endif +# endif +#endif /* !defined(__cpp_lib_list_remove_return_type) && defined(__glibcxx_want_list_remove_return_type) */ +#undef __glibcxx_want_list_remove_return_type + +#if !defined(__cpp_lib_polymorphic_allocator) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_polymorphic_allocator 201902L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_polymorphic_allocator) +# define __cpp_lib_polymorphic_allocator 201902L +# endif +# endif +#endif /* !defined(__cpp_lib_polymorphic_allocator) && defined(__glibcxx_want_polymorphic_allocator) */ +#undef __glibcxx_want_polymorphic_allocator + +#if !defined(__cpp_lib_move_iterator_concept) +# if (__cplusplus >= 202002L) && (__glibcxx_concepts) +# define __glibcxx_move_iterator_concept 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_move_iterator_concept) +# define __cpp_lib_move_iterator_concept 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_move_iterator_concept) && defined(__glibcxx_want_move_iterator_concept) */ +#undef __glibcxx_want_move_iterator_concept + +#if !defined(__cpp_lib_semaphore) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE) +# define __glibcxx_semaphore 201907L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_semaphore) +# define __cpp_lib_semaphore 201907L +# endif +# endif +#endif /* !defined(__cpp_lib_semaphore) && defined(__glibcxx_want_semaphore) */ +#undef __glibcxx_want_semaphore + +#if !defined(__cpp_lib_smart_ptr_for_overwrite) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED +# define __glibcxx_smart_ptr_for_overwrite 202002L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_for_overwrite) +# define __cpp_lib_smart_ptr_for_overwrite 202002L +# endif +# endif +#endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) && defined(__glibcxx_want_smart_ptr_for_overwrite) */ +#undef __glibcxx_want_smart_ptr_for_overwrite + +#if !defined(__cpp_lib_syncbuf) +# if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED +# define __glibcxx_syncbuf 201803L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_syncbuf) +# define __cpp_lib_syncbuf 201803L +# endif +# endif +#endif /* !defined(__cpp_lib_syncbuf) && defined(__glibcxx_want_syncbuf) */ +#undef __glibcxx_want_syncbuf + +#if !defined(__cpp_lib_byteswap) +# if (__cplusplus >= 202100L) +# define __glibcxx_byteswap 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_byteswap) +# define __cpp_lib_byteswap 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_byteswap) && defined(__glibcxx_want_byteswap) */ +#undef __glibcxx_want_byteswap + +#if !defined(__cpp_lib_constexpr_charconv) +# if (__cplusplus >= 202100L) +# define __glibcxx_constexpr_charconv 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_charconv) +# define __cpp_lib_constexpr_charconv 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_charconv) && defined(__glibcxx_want_constexpr_charconv) */ +#undef __glibcxx_want_constexpr_charconv + +#if !defined(__cpp_lib_constexpr_typeinfo) +# if (__cplusplus >= 202100L) +# define __glibcxx_constexpr_typeinfo 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_typeinfo) +# define __cpp_lib_constexpr_typeinfo 202106L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_typeinfo) && defined(__glibcxx_want_constexpr_typeinfo) */ +#undef __glibcxx_want_constexpr_typeinfo + +#if !defined(__cpp_lib_expected) +# if (__cplusplus >= 202100L) && (__cpp_concepts >= 202002L) +# define __glibcxx_expected 202211L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_expected) +# define __cpp_lib_expected 202211L +# endif +# endif +#endif /* !defined(__cpp_lib_expected) && defined(__glibcxx_want_expected) */ +#undef __glibcxx_want_expected + +#if !defined(__cpp_lib_freestanding_algorithm) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_algorithm 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_algorithm) +# define __cpp_lib_freestanding_algorithm 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_algorithm) && defined(__glibcxx_want_freestanding_algorithm) */ +#undef __glibcxx_want_freestanding_algorithm + +#if !defined(__cpp_lib_freestanding_array) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_array 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_array) +# define __cpp_lib_freestanding_array 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_array) && defined(__glibcxx_want_freestanding_array) */ +#undef __glibcxx_want_freestanding_array + +#if !defined(__cpp_lib_freestanding_cstring) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_cstring 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_cstring) +# define __cpp_lib_freestanding_cstring 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_cstring) && defined(__glibcxx_want_freestanding_cstring) */ +#undef __glibcxx_want_freestanding_cstring + +#if !defined(__cpp_lib_freestanding_expected) +# if (__cplusplus >= 202100L) && (__cpp_lib_expected) +# define __glibcxx_freestanding_expected 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_expected) +# define __cpp_lib_freestanding_expected 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_expected) && defined(__glibcxx_want_freestanding_expected) */ +#undef __glibcxx_want_freestanding_expected + +#if !defined(__cpp_lib_freestanding_optional) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_optional 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_optional) +# define __cpp_lib_freestanding_optional 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_optional) && defined(__glibcxx_want_freestanding_optional) */ +#undef __glibcxx_want_freestanding_optional + +#if !defined(__cpp_lib_freestanding_string_view) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_string_view 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_string_view) +# define __cpp_lib_freestanding_string_view 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_string_view) && defined(__glibcxx_want_freestanding_string_view) */ +#undef __glibcxx_want_freestanding_string_view + +#if !defined(__cpp_lib_freestanding_variant) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_variant 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_variant) +# define __cpp_lib_freestanding_variant 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_variant) && defined(__glibcxx_want_freestanding_variant) */ +#undef __glibcxx_want_freestanding_variant + +#if !defined(__cpp_lib_invoke_r) +# if (__cplusplus >= 202100L) +# define __glibcxx_invoke_r 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_invoke_r) +# define __cpp_lib_invoke_r 202106L +# endif +# endif +#endif /* !defined(__cpp_lib_invoke_r) && defined(__glibcxx_want_invoke_r) */ +#undef __glibcxx_want_invoke_r + +#if !defined(__cpp_lib_is_scoped_enum) +# if (__cplusplus >= 202100L) +# define __glibcxx_is_scoped_enum 202011L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_scoped_enum) +# define __cpp_lib_is_scoped_enum 202011L +# endif +# endif +#endif /* !defined(__cpp_lib_is_scoped_enum) && defined(__glibcxx_want_is_scoped_enum) */ +#undef __glibcxx_want_is_scoped_enum + +#if !defined(__cpp_lib_reference_from_temporary) +# if (__cplusplus >= 202100L) && (__has_builtin(__reference_constructs_from_temporary) && __has_builtin(__reference_converts_from_temporary)) +# define __glibcxx_reference_from_temporary 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_reference_from_temporary) +# define __cpp_lib_reference_from_temporary 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_reference_from_temporary) && defined(__glibcxx_want_reference_from_temporary) */ +#undef __glibcxx_want_reference_from_temporary + +#if !defined(__cpp_lib_ranges_to_container) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_ranges_to_container 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_to_container) +# define __cpp_lib_ranges_to_container 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_to_container) && defined(__glibcxx_want_ranges_to_container) */ +#undef __glibcxx_want_ranges_to_container + +#if !defined(__cpp_lib_ranges_zip) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_zip 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_zip) +# define __cpp_lib_ranges_zip 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_zip) && defined(__glibcxx_want_ranges_zip) */ +#undef __glibcxx_want_ranges_zip + +#if !defined(__cpp_lib_ranges_chunk) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_chunk 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_chunk) +# define __cpp_lib_ranges_chunk 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_chunk) && defined(__glibcxx_want_ranges_chunk) */ +#undef __glibcxx_want_ranges_chunk + +#if !defined(__cpp_lib_ranges_slide) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_slide 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_slide) +# define __cpp_lib_ranges_slide 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_slide) && defined(__glibcxx_want_ranges_slide) */ +#undef __glibcxx_want_ranges_slide + +#if !defined(__cpp_lib_ranges_chunk_by) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_chunk_by 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_chunk_by) +# define __cpp_lib_ranges_chunk_by 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_chunk_by) && defined(__glibcxx_want_ranges_chunk_by) */ +#undef __glibcxx_want_ranges_chunk_by + +#if !defined(__cpp_lib_ranges_join_with) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_join_with 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_join_with) +# define __cpp_lib_ranges_join_with 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_join_with) && defined(__glibcxx_want_ranges_join_with) */ +#undef __glibcxx_want_ranges_join_with + +#if !defined(__cpp_lib_ranges_repeat) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_repeat 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_repeat) +# define __cpp_lib_ranges_repeat 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_repeat) && defined(__glibcxx_want_ranges_repeat) */ +#undef __glibcxx_want_ranges_repeat + +#if !defined(__cpp_lib_ranges_stride) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_stride 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_stride) +# define __cpp_lib_ranges_stride 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_stride) && defined(__glibcxx_want_ranges_stride) */ +#undef __glibcxx_want_ranges_stride + +#if !defined(__cpp_lib_ranges_cartesian_product) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_cartesian_product 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_cartesian_product) +# define __cpp_lib_ranges_cartesian_product 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_cartesian_product) && defined(__glibcxx_want_ranges_cartesian_product) */ +#undef __glibcxx_want_ranges_cartesian_product + +#if !defined(__cpp_lib_ranges_as_rvalue) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_as_rvalue 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_as_rvalue) +# define __cpp_lib_ranges_as_rvalue 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_as_rvalue) && defined(__glibcxx_want_ranges_as_rvalue) */ +#undef __glibcxx_want_ranges_as_rvalue + +#if !defined(__cpp_lib_ranges_as_const) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_as_const 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_as_const) +# define __cpp_lib_ranges_as_const 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_as_const) && defined(__glibcxx_want_ranges_as_const) */ +#undef __glibcxx_want_ranges_as_const + +#if !defined(__cpp_lib_ranges_enumerate) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_enumerate 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_enumerate) +# define __cpp_lib_ranges_enumerate 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_enumerate) && defined(__glibcxx_want_ranges_enumerate) */ +#undef __glibcxx_want_ranges_enumerate + +#if !defined(__cpp_lib_ranges_fold) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_fold 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_fold) +# define __cpp_lib_ranges_fold 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_fold) && defined(__glibcxx_want_ranges_fold) */ +#undef __glibcxx_want_ranges_fold + +#if !defined(__cpp_lib_ranges_contains) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_contains 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_contains) +# define __cpp_lib_ranges_contains 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_contains) && defined(__glibcxx_want_ranges_contains) */ +#undef __glibcxx_want_ranges_contains + +#if !defined(__cpp_lib_ranges_iota) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_iota 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_iota) +# define __cpp_lib_ranges_iota 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_iota) && defined(__glibcxx_want_ranges_iota) */ +#undef __glibcxx_want_ranges_iota + +#if !defined(__cpp_lib_ranges_find_last) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_find_last 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_find_last) +# define __cpp_lib_ranges_find_last 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_find_last) && defined(__glibcxx_want_ranges_find_last) */ +#undef __glibcxx_want_ranges_find_last + +#if !defined(__cpp_lib_constexpr_bitset) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__cpp_constexpr_dynamic_alloc) +# define __glibcxx_constexpr_bitset 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_bitset) +# define __cpp_lib_constexpr_bitset 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_bitset) && defined(__glibcxx_want_constexpr_bitset) */ +#undef __glibcxx_want_constexpr_bitset + +#if !defined(__cpp_lib_stdatomic_h) +# if (__cplusplus >= 202100L) +# define __glibcxx_stdatomic_h 202011L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_stdatomic_h) +# define __cpp_lib_stdatomic_h 202011L +# endif +# endif +#endif /* !defined(__cpp_lib_stdatomic_h) && defined(__glibcxx_want_stdatomic_h) */ +#undef __glibcxx_want_stdatomic_h + +#if !defined(__cpp_lib_adaptor_iterator_pair_constructor) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_adaptor_iterator_pair_constructor 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_adaptor_iterator_pair_constructor) +# define __cpp_lib_adaptor_iterator_pair_constructor 202106L +# endif +# endif +#endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) && defined(__glibcxx_want_adaptor_iterator_pair_constructor) */ +#undef __glibcxx_want_adaptor_iterator_pair_constructor + +#if !defined(__cpp_lib_formatters) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_formatters 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_formatters) +# define __cpp_lib_formatters 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_formatters) && defined(__glibcxx_want_formatters) */ +#undef __glibcxx_want_formatters + +#if !defined(__cpp_lib_forward_like) +# if (__cplusplus >= 202100L) +# define __glibcxx_forward_like 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_forward_like) +# define __cpp_lib_forward_like 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_forward_like) && defined(__glibcxx_want_forward_like) */ +#undef __glibcxx_want_forward_like + +#if !defined(__cpp_lib_generator) +# if (__cplusplus >= 202100L) && (__glibcxx_coroutine && __cpp_sized_deallocation) +# define __glibcxx_generator 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_generator) +# define __cpp_lib_generator 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_generator) && defined(__glibcxx_want_generator) */ +#undef __glibcxx_want_generator + +#if !defined(__cpp_lib_ios_noreplace) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_ios_noreplace 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ios_noreplace) +# define __cpp_lib_ios_noreplace 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_ios_noreplace) && defined(__glibcxx_want_ios_noreplace) */ +#undef __glibcxx_want_ios_noreplace + +#if !defined(__cpp_lib_move_only_function) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_move_only_function 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_move_only_function) +# define __cpp_lib_move_only_function 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_move_only_function) && defined(__glibcxx_want_move_only_function) */ +#undef __glibcxx_want_move_only_function + +#if !defined(__cpp_lib_out_ptr) +# if (__cplusplus >= 202100L) +# define __glibcxx_out_ptr 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_out_ptr) +# define __cpp_lib_out_ptr 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_out_ptr) && defined(__glibcxx_want_out_ptr) */ +#undef __glibcxx_want_out_ptr + +#if !defined(__cpp_lib_print) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_print 202211L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_print) +# define __cpp_lib_print 202211L +# endif +# endif +#endif /* !defined(__cpp_lib_print) && defined(__glibcxx_want_print) */ +#undef __glibcxx_want_print + +#if !defined(__cpp_lib_spanstream) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__glibcxx_span) +# define __glibcxx_spanstream 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_spanstream) +# define __cpp_lib_spanstream 202106L +# endif +# endif +#endif /* !defined(__cpp_lib_spanstream) && defined(__glibcxx_want_spanstream) */ +#undef __glibcxx_want_spanstream + +#if !defined(__cpp_lib_stacktrace) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (_GLIBCXX_HAVE_STACKTRACE) +# define __glibcxx_stacktrace 202011L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_stacktrace) +# define __cpp_lib_stacktrace 202011L +# endif +# endif +#endif /* !defined(__cpp_lib_stacktrace) && defined(__glibcxx_want_stacktrace) */ +#undef __glibcxx_want_stacktrace + +#if !defined(__cpp_lib_string_contains) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_string_contains 202011L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_contains) +# define __cpp_lib_string_contains 202011L +# endif +# endif +#endif /* !defined(__cpp_lib_string_contains) && defined(__glibcxx_want_string_contains) */ +#undef __glibcxx_want_string_contains + +#if !defined(__cpp_lib_string_resize_and_overwrite) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_string_resize_and_overwrite 202110L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_resize_and_overwrite) +# define __cpp_lib_string_resize_and_overwrite 202110L +# endif +# endif +#endif /* !defined(__cpp_lib_string_resize_and_overwrite) && defined(__glibcxx_want_string_resize_and_overwrite) */ +#undef __glibcxx_want_string_resize_and_overwrite + +#if !defined(__cpp_lib_to_underlying) +# if (__cplusplus >= 202100L) +# define __glibcxx_to_underlying 202102L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_underlying) +# define __cpp_lib_to_underlying 202102L +# endif +# endif +#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ +#undef __glibcxx_want_to_underlying + +#if !defined(__cpp_lib_tuple_like) +# if (__cplusplus >= 202100L) +# define __glibcxx_tuple_like 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_tuple_like) +# define __cpp_lib_tuple_like 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_tuple_like) && defined(__glibcxx_want_tuple_like) */ +#undef __glibcxx_want_tuple_like + +#if !defined(__cpp_lib_unreachable) +# if (__cplusplus >= 202100L) +# define __glibcxx_unreachable 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unreachable) +# define __cpp_lib_unreachable 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ +#undef __glibcxx_want_unreachable + +#if !defined(__cpp_lib_fstream_native_handle) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_fstream_native_handle 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_fstream_native_handle) +# define __cpp_lib_fstream_native_handle 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_fstream_native_handle) && defined(__glibcxx_want_fstream_native_handle) */ +#undef __glibcxx_want_fstream_native_handle + +#if !defined(__cpp_lib_ratio) +# if (__cplusplus > 202302L) +# define __glibcxx_ratio 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ratio) +# define __cpp_lib_ratio 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_ratio) && defined(__glibcxx_want_ratio) */ +#undef __glibcxx_want_ratio + +#if !defined(__cpp_lib_reference_wrapper) +# if (__cplusplus > 202302L) +# define __glibcxx_reference_wrapper 202403L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_reference_wrapper) +# define __cpp_lib_reference_wrapper 202403L +# endif +# endif +#endif /* !defined(__cpp_lib_reference_wrapper) && defined(__glibcxx_want_reference_wrapper) */ +#undef __glibcxx_want_reference_wrapper + +#if !defined(__cpp_lib_saturation_arithmetic) +# if (__cplusplus > 202302L) +# define __glibcxx_saturation_arithmetic 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_saturation_arithmetic) +# define __cpp_lib_saturation_arithmetic 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_saturation_arithmetic) && defined(__glibcxx_want_saturation_arithmetic) */ +#undef __glibcxx_want_saturation_arithmetic + +#if !defined(__cpp_lib_text_encoding) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED && (_GLIBCXX_USE_NL_LANGINFO_L) +# define __glibcxx_text_encoding 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_text_encoding) +# define __cpp_lib_text_encoding 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_text_encoding) && defined(__glibcxx_want_text_encoding) */ +#undef __glibcxx_want_text_encoding + +#if !defined(__cpp_lib_to_string) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED && (__glibcxx_to_chars) +# define __glibcxx_to_string 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_string) +# define __cpp_lib_to_string 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_to_string) && defined(__glibcxx_want_to_string) */ +#undef __glibcxx_want_to_string + +#undef __glibcxx_want_all diff --git a/template/sysroot/include/bitset b/template/sysroot/include/bitset new file mode 100644 index 0000000..ccd6d19 --- /dev/null +++ b/template/sysroot/include/bitset @@ -0,0 +1,1746 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/bitset + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BITSET +#define _GLIBCXX_BITSET 1 + +#pragma GCC system_header + +#include // For invalid_argument, out_of_range, + // overflow_error +#include // For std::fill + +#if _GLIBCXX_HOSTED +# include +# include +# include +#endif + +#if __cplusplus >= 201103L +# include +#endif + +#define __glibcxx_want_constexpr_bitset +#include + +#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) +#define _GLIBCXX_BITSET_WORDS(__n) \ + ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ + ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1)) + +#define _GLIBCXX_BITSET_BITS_PER_ULL (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * Base class, general case. It is a class invariant that _Nw will be + * nonnegative. + * + * See documentation for bitset. + */ + template + struct _Base_bitset + { + typedef unsigned long _WordT; + + /// 0 is the least significant word. + _WordT _M_w[_Nw]; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w() { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept + : _M_w{ _WordT(__val) +#if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__ + , _WordT(__val >> _GLIBCXX_BITSET_BITS_PER_WORD) +#endif + } { } +#else + _Base_bitset(unsigned long __val) + : _M_w() + { _M_w[0] = __val; } +#endif + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _GLIBCXX14_CONSTEXPR _WordT& + _M_getword(size_t __pos) _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t __pos) const _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + +#if __cplusplus >= 201103L + constexpr const _WordT* + _M_getdata() const noexcept + { return _M_w; } +#endif + + _GLIBCXX23_CONSTEXPR _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + _GLIBCXX23_CONSTEXPR void + _M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] &= __x._M_w[__i]; + } + + _GLIBCXX14_CONSTEXPR void + _M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] |= __x._M_w[__i]; + } + + _GLIBCXX14_CONSTEXPR void + _M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] ^= __x._M_w[__i]; + } + + _GLIBCXX14_CONSTEXPR void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + _GLIBCXX14_CONSTEXPR void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + _GLIBCXX14_CONSTEXPR void + _M_do_flip() _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] = ~_M_w[__i]; + } + + _GLIBCXX14_CONSTEXPR void + _M_do_set() _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201402L + if (__builtin_is_constant_evaluated()) + { + for (_WordT& __w : _M_w) + __w = ~static_cast<_WordT>(0);; + return; + } +#endif + __builtin_memset(_M_w, 0xFF, _Nw * sizeof(_WordT)); + } + + _GLIBCXX14_CONSTEXPR void + _M_do_reset() _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201402L + if (__builtin_is_constant_evaluated()) + { + for (_WordT& __w : _M_w) + __w = 0; + return; + } +#endif + __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); + } + + _GLIBCXX14_CONSTEXPR bool + _M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; ++__i) + if (_M_w[__i] != __x._M_w[__i]) + return false; + return true; + } + + template + _GLIBCXX14_CONSTEXPR bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw - 1; __i++) + if (_M_w[__i] != ~static_cast<_WordT>(0)) + return false; + return _M_hiword() == (~static_cast<_WordT>(0) + >> (_Nw * _GLIBCXX_BITSET_BITS_PER_WORD + - _Nb)); + } + + _GLIBCXX14_CONSTEXPR bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + if (_M_w[__i] != static_cast<_WordT>(0)) + return true; + return false; + } + + _GLIBCXX14_CONSTEXPR size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { + size_t __result = 0; + for (size_t __i = 0; __i < _Nw; __i++) + __result += __builtin_popcountl(_M_w[__i]); + return __result; + } + + _GLIBCXX14_CONSTEXPR unsigned long + _M_do_to_ulong() const; + +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR unsigned long long + _M_do_to_ullong() const; +#endif + + // find first "on" bit + _GLIBCXX14_CONSTEXPR size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT; + + // find the next "on" bit that follows "prev" + _GLIBCXX14_CONSTEXPR size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT; + }; + + // Definitions of non-inline functions from _Base_bitset. + template + _GLIBCXX14_CONSTEXPR void + _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + + if (__offset == 0) + for (size_t __n = _Nw - 1; __n >= __wshift; --__n) + _M_w[__n] = _M_w[__n - __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = _Nw - 1; __n > __wshift; --__n) + _M_w[__n] = ((_M_w[__n - __wshift] << __offset) + | (_M_w[__n - __wshift - 1] >> __sub_offset)); + _M_w[__wshift] = _M_w[0] << __offset; + } + + std::fill(_M_w + 0, _M_w + __wshift, static_cast<_WordT>(0)); + } + } + + template + _GLIBCXX14_CONSTEXPR void + _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __limit = _Nw - __wshift - 1; + + if (__offset == 0) + for (size_t __n = 0; __n <= __limit; ++__n) + _M_w[__n] = _M_w[__n + __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = 0; __n < __limit; ++__n) + _M_w[__n] = ((_M_w[__n + __wshift] >> __offset) + | (_M_w[__n + __wshift + 1] << __sub_offset)); + _M_w[__limit] = _M_w[_Nw-1] >> __offset; + } + + std::fill(_M_w + __limit + 1, _M_w + _Nw, static_cast<_WordT>(0)); + } + } + + template + _GLIBCXX14_CONSTEXPR unsigned long + _Base_bitset<_Nw>::_M_do_to_ulong() const + { + for (size_t __i = 1; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ulong")); + return _M_w[0]; + } + +#if __cplusplus >= 201103L + template + _GLIBCXX14_CONSTEXPR unsigned long long + _Base_bitset<_Nw>::_M_do_to_ullong() const + { +#if __SIZEOF_LONG_LONG__ == __SIZEOF_LONG__ + return _M_do_to_ulong(); +#else + for (size_t __i = 2; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ullong")); + + return _M_w[0] + (static_cast(_M_w[1]) + << _GLIBCXX_BITSET_BITS_PER_WORD); +#endif + } +#endif // C++11 + + template + _GLIBCXX14_CONSTEXPR size_t + _Base_bitset<_Nw>:: + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + { + _WordT __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } + + template + _GLIBCXX14_CONSTEXPR size_t + _Base_bitset<_Nw>:: + _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT + { + // make bound inclusive + ++__prev; + + // check out of bounds + if (__prev >= _Nw * _GLIBCXX_BITSET_BITS_PER_WORD) + return __not_found; + + // search first word + size_t __i = _S_whichword(__prev); + _WordT __thisword = _M_w[__i]; + + // mask off bits below bound + __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev); + + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + + // check subsequent words + __i++; + for (; __i < _Nw; __i++) + { + __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } // end _M_do_find_next + + /** + * Base class, specialization for a single word. + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<1> + { + typedef unsigned long _WordT; + _WordT _M_w; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w(0) + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept +#else + _Base_bitset(unsigned long __val) +#endif + : _M_w(__val) + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _GLIBCXX14_CONSTEXPR _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + constexpr const _WordT* + _M_getdata() const noexcept + { return &_M_w; } +#endif + + _GLIBCXX14_CONSTEXPR _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX14_CONSTEXPR void + _M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w &= __x._M_w; } + + _GLIBCXX14_CONSTEXPR void + _M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w |= __x._M_w; } + + _GLIBCXX14_CONSTEXPR void + _M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w ^= __x._M_w; } + + _GLIBCXX14_CONSTEXPR void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w <<= __shift; } + + _GLIBCXX14_CONSTEXPR void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w >>= __shift; } + + _GLIBCXX14_CONSTEXPR void + _M_do_flip() _GLIBCXX_NOEXCEPT + { _M_w = ~_M_w; } + + _GLIBCXX14_CONSTEXPR void + _M_do_set() _GLIBCXX_NOEXCEPT + { _M_w = ~static_cast<_WordT>(0); } + + _GLIBCXX14_CONSTEXPR void + _M_do_reset() _GLIBCXX_NOEXCEPT + { _M_w = 0; } + + _GLIBCXX14_CONSTEXPR bool + _M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT + { return _M_w == __x._M_w; } + + template + _GLIBCXX14_CONSTEXPR bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return _M_w == (~static_cast<_WordT>(0) + >> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); } + + _GLIBCXX14_CONSTEXPR bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return _M_w != 0; } + + _GLIBCXX14_CONSTEXPR size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return __builtin_popcountl(_M_w); } + + _GLIBCXX14_CONSTEXPR unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + constexpr unsigned long long + _M_do_to_ullong() const noexcept + { return _M_w; } +#endif + + _GLIBCXX14_CONSTEXPR size_t + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + if (_M_w != 0) + return __builtin_ctzl(_M_w); + else + return __not_found; + } + + // find the next "on" bit that follows "prev" + _GLIBCXX14_CONSTEXPR size_t + _M_do_find_next(size_t __prev, size_t __not_found) const + _GLIBCXX_NOEXCEPT + { + ++__prev; + if (__prev >= ((size_t) _GLIBCXX_BITSET_BITS_PER_WORD)) + return __not_found; + + _WordT __x = _M_w >> __prev; + if (__x != 0) + return __builtin_ctzl(__x) + __prev; + else + return __not_found; + } + }; + + /** + * Base class, specialization for no storage (zero-length %bitset). + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<0> + { + typedef unsigned long _WordT; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long) noexcept +#else + _Base_bitset(unsigned long) +#endif + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + // This would normally give access to the data. The bounds-checking + // in the bitset class will prevent the user from getting this far, + // but this must fail if the user calls _Unchecked_set directly. + // Let's not penalize zero-length users unless they actually + // make an unchecked call; all the memory ugliness is therefore + // localized to this single should-never-get-this-far function. + __attribute__((__noreturn__)) + _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { __throw_out_of_range(__N("_Base_bitset::_M_getword")); } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX14_CONSTEXPR void + _M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_flip() _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_set() _GLIBCXX_NOEXCEPT + { } + + _GLIBCXX14_CONSTEXPR void + _M_do_reset() _GLIBCXX_NOEXCEPT + { } + + // Are all empty bitsets equal to each other? Are they equal to + // themselves? How to compare a thing which has no state? What is + // the sound of one zero-length bitset clapping? + _GLIBCXX_CONSTEXPR bool + _M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT + { return true; } + + template + _GLIBCXX_CONSTEXPR bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return true; } + + _GLIBCXX_CONSTEXPR bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return false; } + + _GLIBCXX_CONSTEXPR size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX_CONSTEXPR unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return 0; } + +#if __cplusplus >= 201103L + constexpr unsigned long long + _M_do_to_ullong() const noexcept + { return 0; } +#endif + + // Normally "not found" is the size, but that could also be + // misinterpreted as an index in this corner case. Oh well. + _GLIBCXX_CONSTEXPR size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX_CONSTEXPR size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + }; + + + // Helper class to zero out the unused high-order bits in the highest word. + template + struct _Sanitize + { + typedef unsigned long _WordT; + + static _GLIBCXX14_CONSTEXPR void + _S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT + { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); } + }; + + template<> + struct _Sanitize<0> + { + typedef unsigned long _WordT; + + static _GLIBCXX14_CONSTEXPR void + _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } + }; + +#if __cplusplus >= 201103L + template + struct _Sanitize_val + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val; } + }; + + template + struct _Sanitize_val<_Nb, true> + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val & ~((~static_cast(0)) << _Nb); } + }; + + namespace __bitset + { +#if _GLIBCXX_HOSTED + template + using __string = std::basic_string<_CharT>; +#else + template + struct __string + { + using size_type = size_t; + static constexpr size_type npos = size_type(-1); + + struct traits_type + { + static _GLIBCXX14_CONSTEXPR size_t + length(const _CharT* __s) noexcept + { + size_t __n = 0; + while (__s[__n]) + __n++; + return __n; + } + + static constexpr bool + eq(_CharT __l, _CharT __r) noexcept + { return __l == __r; } + }; + }; +#endif // HOSTED + } // namespace __bitset +#endif // C++11 + + /** + * @brief The %bitset class represents a @e fixed-size sequence of bits. + * @ingroup utilities + * + * (Note that %bitset does @e not meet the formal requirements of a + * container. Mainly, it lacks iterators.) + * + * The template argument, @a Nb, may be any non-negative number, + * specifying the number of bits (e.g., "0", "12", "1024*1024"). + * + * In the general unoptimized case, storage is allocated in word-sized + * blocks. Let B be the number of bits in a word, then (Nb+(B-1))/B + * words will be used for storage. B - Nb%B bits are unused. (They are + * the high-order bits in the highest word.) It is a class invariant + * that those unused bits are always zero. + * + * If you think of %bitset as a simple array of bits, be + * aware that your mental picture is reversed: a %bitset behaves + * the same way as bits in integers do, with the bit at index 0 in + * the least significant / right-hand position, and the bit at + * index Nb-1 in the most significant / left-hand position. + * Thus, unlike other containers, a %bitset's index counts from + * right to left, to put it very loosely. + * + * This behavior is preserved when translating to and from strings. For + * example, the first line of the following program probably prints + * b('a') is 0001100001 on a modern ASCII system. + * + * @code + * #include + * #include + * #include + * + * using namespace std; + * + * int main() + * { + * long a = 'a'; + * bitset<10> b(a); + * + * cout << "b('a') is " << b << endl; + * + * ostringstream s; + * s << b; + * string str = s.str(); + * cout << "index 3 in the string is " << str[3] << " but\n" + * << "index 3 in the bitset is " << b[3] << endl; + * } + * @endcode + * + * Also see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_containers.html + * for a description of extensions. + * + * Most of the actual code isn't contained in %bitset<> itself, but in the + * base class _Base_bitset. The base class works with whole words, not with + * individual bits. This allows us to specialize _Base_bitset for the + * important special case where the %bitset is only a single word. + * + * Extra confusion can result due to the fact that the storage for + * _Base_bitset @e is a regular array, and is indexed as such. This is + * carefully encapsulated. + */ + template + class bitset + : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> + { + private: + typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; + typedef unsigned long _WordT; + +#if _GLIBCXX_HOSTED + template + _GLIBCXX23_CONSTEXPR + void + _M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s, + size_t __position) const + { + if (__position > __s.size()) + __throw_out_of_range_fmt(__N("bitset::bitset: __position " + "(which is %zu) > __s.size() " + "(which is %zu)"), + __position, __s.size()); + } +#endif // HOSTED + + _GLIBCXX23_CONSTEXPR + void _M_check(size_t __position, const char *__s) const + { + if (__position >= _Nb) + __throw_out_of_range_fmt(__N("%s: __position (which is %zu) " + ">= _Nb (which is %zu)"), + __s, __position, _Nb); + } + + _GLIBCXX23_CONSTEXPR + void + _M_do_sanitize() _GLIBCXX_NOEXCEPT + { + typedef _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD> __sanitize_type; + __sanitize_type::_S_do_sanitize(this->_M_hiword()); + } + +#if __cplusplus >= 201103L + friend struct std::hash; +#endif + + public: + /** + * This encapsulates the concept of a single bit. An instance of this + * class is a proxy for an actual bit; this way the individual bit + * operations are done as faster word-size bitwise instructions. + * + * Most users will never need to use this class directly; conversions + * to and from bool are automatic and should be transparent. Overloaded + * operators help to preserve the illusion. + * + * (On a typical system, this bit %reference is 64 + * times the size of an actual bit. Ha.) + */ + class reference + { + friend class bitset; + + _WordT* _M_wp; + size_t _M_bpos; + + // left undefined + reference(); + + public: + _GLIBCXX23_CONSTEXPR + reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT + { + _M_wp = &__b._M_getword(__pos); + _M_bpos = _Base::_S_whichbit(__pos); + } + +#if __cplusplus >= 201103L + reference(const reference&) = default; +#endif + +#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~reference() _GLIBCXX_NOEXCEPT + { } + + // For b[i] = __x; + _GLIBCXX23_CONSTEXPR + reference& + operator=(bool __x) _GLIBCXX_NOEXCEPT + { + if (__x) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // For b[i] = b[__j]; + _GLIBCXX23_CONSTEXPR + reference& + operator=(const reference& __j) _GLIBCXX_NOEXCEPT + { + if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // Flips the bit + _GLIBCXX23_CONSTEXPR + bool + operator~() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } + + // For __x = b[i]; + _GLIBCXX23_CONSTEXPR + operator bool() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } + + // For b[i].flip(); + _GLIBCXX23_CONSTEXPR + reference& + flip() _GLIBCXX_NOEXCEPT + { + *_M_wp ^= _Base::_S_maskbit(_M_bpos); + return *this; + } + }; + friend class reference; + + // 23.3.5.1 constructors: + /// All bits set to zero. + _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT + { } + + /// Initial bits bitwise-copied from a single word (others set to zero). +#if __cplusplus >= 201103L + constexpr bitset(unsigned long long __val) noexcept + : _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { } +#else + bitset(unsigned long __val) + : _Base(__val) + { _M_do_sanitize(); } +#endif + +#if _GLIBCXX_HOSTED + /** + * Use a subset of a string. + * @param __s A string of @a 0 and @a 1 characters. + * @param __position Index of the first character in @a __s to use; + * defaults to zero. + * @throw std::out_of_range If @a pos is bigger the size of @a __s. + * @throw std::invalid_argument If a character appears in the string + * which is neither @a 0 nor @a 1. + */ + template + _GLIBCXX23_CONSTEXPR + explicit + bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, + size_t __position = 0) + : _Base() + { + _M_check_initial_position(__s, __position); + _M_copy_from_string(__s, __position, + std::basic_string<_CharT, _Traits, _Alloc>::npos, + _CharT('0'), _CharT('1')); + } + + /** + * Use a subset of a string. + * @param __s A string of @a 0 and @a 1 characters. + * @param __position Index of the first character in @a __s to use. + * @param __n The number of characters to copy. + * @throw std::out_of_range If @a __position is bigger the size + * of @a __s. + * @throw std::invalid_argument If a character appears in the string + * which is neither @a 0 nor @a 1. + */ + template + _GLIBCXX23_CONSTEXPR + bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, + size_t __position, size_t __n) + : _Base() + { + _M_check_initial_position(__s, __position); + _M_copy_from_string(__s, __position, __n, _CharT('0'), _CharT('1')); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 396. what are characters zero and one. + template + _GLIBCXX23_CONSTEXPR + bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, + size_t __position, size_t __n, + _CharT __zero, _CharT __one = _CharT('1')) + : _Base() + { + _M_check_initial_position(__s, __position); + _M_copy_from_string(__s, __position, __n, __zero, __one); + } +#endif // HOSTED + +#if __cplusplus >= 201103L + /** + * Construct from a character %array. + * @param __str An %array of characters @a zero and @a one. + * @param __n The number of characters to use. + * @param __zero The character corresponding to the value 0. + * @param __one The character corresponding to the value 1. + * @throw std::invalid_argument If a character appears in the string + * which is neither @a __zero nor @a __one. + */ + template + [[__gnu__::__nonnull__]] + _GLIBCXX23_CONSTEXPR + explicit + bitset(const _CharT* __str, + typename __bitset::__string<_CharT>::size_type __n + = __bitset::__string<_CharT>::npos, + _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) + : _Base() + { +#if _GLIBCXX_HOSTED + if (!__str) + __throw_logic_error(__N("bitset::bitset(const _CharT*, ...)")); +#endif + using _Traits = typename __bitset::__string<_CharT>::traits_type; + + if (__n == __bitset::__string<_CharT>::npos) + __n = _Traits::length(__str); + _M_copy_from_ptr<_CharT, _Traits>(__str, __n, 0, __n, __zero, __one); + } +#endif // C++11 + + // 23.3.5.2 bitset operations: + ///@{ + /** + * Operations on bitsets. + * @param __rhs A same-sized bitset. + * + * These should be self-explanatory. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_and(__rhs); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_or(__rhs); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_xor(__rhs); + return *this; + } + ///@} + + ///@{ + /** + * Operations on bitsets. + * @param __position The number of places to shift. + * + * These should be self-explanatory. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + operator<<=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + { + this->_M_do_left_shift(__position); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + operator>>=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + this->_M_do_right_shift(__position); + else + this->_M_do_reset(); + return *this; + } + ///@} + + ///@{ + /** + * These versions of single-bit set, reset, flip, and test are + * extensions from the SGI version. They do no range checking. + * @ingroup SGIextensions + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + _Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + _Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT + { + if (__val) + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + else + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + _Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + _Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX_CONSTEXPR bool + _Unchecked_test(size_t __pos) const _GLIBCXX_NOEXCEPT + { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) + != static_cast<_WordT>(0)); } + ///@} + + // Set, reset, and flip. + /** + * @brief Sets every bit to true. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + set() _GLIBCXX_NOEXCEPT + { + this->_M_do_set(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Sets a given bit to a particular value. + * @param __position The index of the bit. + * @param __val Either true or false, defaults to true. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + set(size_t __position, bool __val = true) + { + this->_M_check(__position, __N("bitset::set")); + return _Unchecked_set(__position, __val); + } + + /** + * @brief Sets every bit to false. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + reset() _GLIBCXX_NOEXCEPT + { + this->_M_do_reset(); + return *this; + } + + /** + * @brief Sets a given bit to false. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + * + * Same as writing @c set(pos,false). + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + reset(size_t __position) + { + this->_M_check(__position, __N("bitset::reset")); + return _Unchecked_reset(__position); + } + + /** + * @brief Toggles every bit to its opposite value. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + flip() _GLIBCXX_NOEXCEPT + { + this->_M_do_flip(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Toggles a given bit to its opposite value. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + _GLIBCXX23_CONSTEXPR + bitset<_Nb>& + flip(size_t __position) + { + this->_M_check(__position, __N("bitset::flip")); + return _Unchecked_flip(__position); + } + + /// See the no-argument flip(). + _GLIBCXX23_CONSTEXPR + bitset<_Nb> + operator~() const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this).flip(); } + + ///@{ + /** + * @brief Array-indexing support. + * @param __position Index into the %bitset. + * @return A bool for a const %bitset. For non-const + * bitsets, an instance of the reference proxy class. + * @note These operators do no range checking and throw no exceptions, + * as required by DR 11 to the standard. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS Note that this implementation already + * resolves DR 11 (items 1 and 2), but does not do the range-checking + * required by that DR's resolution. -pme + * The DR has since been changed: range-checking is a precondition + * (users' responsibility), and these functions must not throw. -pme + */ + _GLIBCXX23_CONSTEXPR + reference + operator[](size_t __position) + { return reference(*this, __position); } + + _GLIBCXX_CONSTEXPR bool + operator[](size_t __position) const + { return _Unchecked_test(__position); } + ///@} + + /** + * @brief Returns a numerical interpretation of the %bitset. + * @return The integral equivalent of the bits. + * @throw std::overflow_error If there are too many bits to be + * represented in an @c unsigned @c long. + */ + _GLIBCXX23_CONSTEXPR + unsigned long + to_ulong() const + { return this->_M_do_to_ulong(); } + +#if __cplusplus >= 201103L + _GLIBCXX23_CONSTEXPR + unsigned long long + to_ullong() const + { return this->_M_do_to_ullong(); } +#endif + +#if _GLIBCXX_HOSTED + /** + * @brief Returns a character interpretation of the %bitset. + * @return The string equivalent of the bits. + * + * Note the ordering of the bits: decreasing character positions + * correspond to increasing bit positions (see the main class notes for + * an example). + */ + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, _Traits, _Alloc> + to_string() const + { + std::basic_string<_CharT, _Traits, _Alloc> __result; + _M_copy_to_string(__result, _CharT('0'), _CharT('1')); + return __result; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 396. what are characters zero and one. + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, _Traits, _Alloc> + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { + std::basic_string<_CharT, _Traits, _Alloc> __result; + _M_copy_to_string(__result, __zero, __one); + return __result; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 434. bitset::to_string() hard to use. + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, _Traits, std::allocator<_CharT> > + to_string() const + { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 853. to_string needs updating with zero and one. + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, _Traits, std::allocator<_CharT> > + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { return to_string<_CharT, _Traits, + std::allocator<_CharT> >(__zero, __one); } + + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> > + to_string() const + { + return to_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> >(); + } + + template + _GLIBCXX23_CONSTEXPR + std::basic_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> > + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { + return to_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> >(__zero, __one); + } + + _GLIBCXX23_CONSTEXPR + std::basic_string, std::allocator > + to_string() const + { + return to_string, + std::allocator >(); + } + + _GLIBCXX23_CONSTEXPR + std::basic_string, std::allocator > + to_string(char __zero, char __one = '1') const + { + return to_string, + std::allocator >(__zero, __one); + } +#endif // HOSTED + + /// Returns the number of bits which are set. + _GLIBCXX23_CONSTEXPR + size_t + count() const _GLIBCXX_NOEXCEPT + { return this->_M_do_count(); } + + /// Returns the total number of bits. + _GLIBCXX_CONSTEXPR size_t + size() const _GLIBCXX_NOEXCEPT + { return _Nb; } + + ///@{ + /// These comparisons for equality/inequality are, well, @e bitwise. + _GLIBCXX23_CONSTEXPR + bool + operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return this->_M_is_equal(__rhs); } + +#if __cpp_impl_three_way_comparison < 201907L + _GLIBCXX23_CONSTEXPR + bool + operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return !this->_M_is_equal(__rhs); } +#endif + ///@} + + /** + * @brief Tests the value of a bit. + * @param __position The index of a bit. + * @return The value at @a pos. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + _GLIBCXX23_CONSTEXPR + bool + test(size_t __position) const + { + this->_M_check(__position, __N("bitset::test")); + return _Unchecked_test(__position); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 693. std::bitset::all() missing. + /** + * @brief Tests whether all the bits are on. + * @return True if all the bits are set. + */ + _GLIBCXX23_CONSTEXPR + bool + all() const _GLIBCXX_NOEXCEPT + { return this->template _M_are_all<_Nb>(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if at least one bit is set. + */ + _GLIBCXX23_CONSTEXPR + bool + any() const _GLIBCXX_NOEXCEPT + { return this->_M_is_any(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if none of the bits are set. + */ + _GLIBCXX23_CONSTEXPR + bool + none() const _GLIBCXX_NOEXCEPT + { return !this->_M_is_any(); } + + ///@{ + /// Self-explanatory. + _GLIBCXX23_CONSTEXPR + bitset<_Nb> + operator<<(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) <<= __position; } + + _GLIBCXX23_CONSTEXPR + bitset<_Nb> + operator>>(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) >>= __position; } + ///@} + + /** + * @brief Finds the index of the first "on" bit. + * @return The index of the first bit set, or size() if not found. + * @ingroup SGIextensions + * @sa _Find_next + */ + _GLIBCXX23_CONSTEXPR + size_t + _Find_first() const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_first(_Nb); } + + /** + * @brief Finds the index of the next "on" bit after prev. + * @return The index of the next bit set, or size() if not found. + * @param __prev Where to start searching. + * @ingroup SGIextensions + * @sa _Find_first + */ + _GLIBCXX23_CONSTEXPR + size_t + _Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_next(__prev, _Nb); } + + private: + // Helper functions for string operations. + template + _GLIBCXX23_CONSTEXPR + void + _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t, + _CharT, _CharT); + +#if _GLIBCXX_HOSTED + template + _GLIBCXX23_CONSTEXPR + void + _M_copy_from_string(const std::basic_string<_CharT, + _Traits, _Alloc>& __s, size_t __pos, size_t __n, + _CharT __zero, _CharT __one) + { _M_copy_from_ptr<_CharT, _Traits>(__s.data(), __s.size(), __pos, __n, + __zero, __one); } + + template + _GLIBCXX23_CONSTEXPR + void + _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>&, + _CharT, _CharT) const; + + template + friend std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>&, bitset<_Nb2>&); + + template + friend std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>&, const bitset<_Nb2>&); +#endif + }; + + // Definitions of non-inline member functions. + template + template + _GLIBCXX23_CONSTEXPR + void + bitset<_Nb>:: + _M_copy_from_ptr(const _CharT* __s, size_t __len, + size_t __pos, size_t __n, _CharT __zero, _CharT __one) + { + reset(); + const size_t __nbits = std::min(_Nb, std::min(__n, size_t(__len - __pos))); + for (size_t __i = __nbits; __i > 0; --__i) + { + const _CharT __c = __s[__pos + __nbits - __i]; + if (_Traits::eq(__c, __zero)) + ; + else if (_Traits::eq(__c, __one)) + _Unchecked_set(__i - 1); + else + __throw_invalid_argument(__N("bitset::_M_copy_from_ptr")); + } + } + +#if _GLIBCXX_HOSTED + template + template + _GLIBCXX23_CONSTEXPR + void + bitset<_Nb>:: + _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>& __s, + _CharT __zero, _CharT __one) const + { + __s.assign(_Nb, __zero); + size_t __n = this->_Find_first(); + while (__n < _Nb) + { + __s[_Nb - __n - 1] = __one; + __n = _Find_next(__n); + } + } +#endif // HOSTED + + // 23.3.5.3 bitset operations: + ///@{ + /** + * @brief Global bitwise operations on bitsets. + * @param __x A bitset. + * @param __y A bitset of the same size as @a __x. + * @return A new bitset. + * + * These should be self-explanatory. + */ + template + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> + operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result &= __y; + return __result; + } + + template + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> + operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result |= __y; + return __result; + } + + template + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> + operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result ^= __y; + return __result; + } + ///@} + +#if _GLIBCXX_HOSTED + ///@{ + /** + * @brief Global I/O operators for bitsets. + * + * Direct I/O between streams and bitsets is supported. Output is + * straightforward. Input will skip whitespace, only accept @a 0 and @a 1 + * characters, and will only extract as many digits as the %bitset will + * hold. + */ + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x) + { + typedef typename _Traits::char_type char_type; + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + struct _Buffer + { + static _GLIBCXX_CONSTEXPR bool _S_use_alloca() { return _Nb <= 256; } + + explicit _Buffer(_CharT* __p) : _M_ptr(__p) { } + + ~_Buffer() + { + if _GLIBCXX17_CONSTEXPR (!_S_use_alloca()) + delete[] _M_ptr; + } + + _CharT* const _M_ptr; + }; + _CharT* __ptr; + if _GLIBCXX17_CONSTEXPR (_Buffer::_S_use_alloca()) + __ptr = (_CharT*)__builtin_alloca(_Nb); + else + __ptr = new _CharT[_Nb]; + const _Buffer __buf(__ptr); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 303. Bitset input operator underspecified + const char_type __zero = __is.widen('0'); + const char_type __one = __is.widen('1'); + + typename __ios_base::iostate __state = __ios_base::goodbit; + typename __istream_type::sentry __sentry(__is); + if (__sentry) + { + __try + { + for (size_t __i = _Nb; __i > 0; --__i) + { + static typename _Traits::int_type __eof = _Traits::eof(); + + typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc(); + if (_Traits::eq_int_type(__c1, __eof)) + { + __state |= __ios_base::eofbit; + break; + } + else + { + const char_type __c2 = _Traits::to_char_type(__c1); + if (_Traits::eq(__c2, __zero)) + *__ptr++ = __zero; + else if (_Traits::eq(__c2, __one)) + *__ptr++ = __one; + else if (_Traits:: + eq_int_type(__is.rdbuf()->sputbackc(__c2), + __eof)) + { + __state |= __ios_base::failbit; + break; + } + } + } + } + __catch(__cxxabiv1::__forced_unwind&) + { + __is._M_setstate(__ios_base::badbit); + __throw_exception_again; + } + __catch(...) + { __is._M_setstate(__ios_base::badbit); } + } + + if _GLIBCXX17_CONSTEXPR (_Nb) + { + if (size_t __len = __ptr - __buf._M_ptr) + __x.template _M_copy_from_ptr<_CharT, _Traits>(__buf._M_ptr, __len, + 0, __len, + __zero, __one); + else + __state |= __ios_base::failbit; + } + if (__state) + __is.setstate(__state); + return __is; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const bitset<_Nb>& __x) + { + std::basic_string<_CharT, _Traits> __tmp; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 396. what are characters zero and one. + const ctype<_CharT>& __ct = use_facet >(__os.getloc()); + __x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1')); + return __os << __tmp; + } + ///@} +#endif // HOSTED + +_GLIBCXX_END_NAMESPACE_CONTAINER +} // namespace std + +#undef _GLIBCXX_BITSET_WORDS +#undef _GLIBCXX_BITSET_BITS_PER_WORD +#undef _GLIBCXX_BITSET_BITS_PER_ULL + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // DR 1182. + /// std::hash specialization for bitset. + template + struct hash<_GLIBCXX_STD_C::bitset<_Nb>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept + { + const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__; + return std::_Hash_impl::hash(__b._M_getdata(), __clength); + } + }; + + template<> + struct hash<_GLIBCXX_STD_C::bitset<0>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept + { return 0; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#if defined _GLIBCXX_DEBUG && _GLIBCXX_HOSTED +# include +#endif + +#endif /* _GLIBCXX_BITSET */ diff --git a/template/sysroot/include/bmi2intrin.h b/template/sysroot/include/bmi2intrin.h new file mode 100644 index 0000000..0ef0ebe --- /dev/null +++ b/template/sysroot/include/bmi2intrin.h @@ -0,0 +1,109 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _BMI2INTRIN_H_INCLUDED +#define _BMI2INTRIN_H_INCLUDED + +#ifndef __BMI2__ +#pragma GCC push_options +#pragma GCC target("bmi2") +#define __DISABLE_BMI2__ +#endif /* __BMI2__ */ + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_bzhi_u32 (unsigned int __X, unsigned int __Y) +{ + return __builtin_ia32_bzhi_si (__X, __Y); +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_pdep_u32 (unsigned int __X, unsigned int __Y) +{ + return __builtin_ia32_pdep_si (__X, __Y); +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_pext_u32 (unsigned int __X, unsigned int __Y) +{ + return __builtin_ia32_pext_si (__X, __Y); +} + +#ifdef __x86_64__ + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_bzhi_u64 (unsigned long long __X, unsigned long long __Y) +{ + return __builtin_ia32_bzhi_di (__X, __Y); +} + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_pdep_u64 (unsigned long long __X, unsigned long long __Y) +{ + return __builtin_ia32_pdep_di (__X, __Y); +} + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_pext_u64 (unsigned long long __X, unsigned long long __Y) +{ + return __builtin_ia32_pext_di (__X, __Y); +} + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mulx_u64 (unsigned long long __X, unsigned long long __Y, + unsigned long long *__P) +{ + unsigned __int128 __res = (unsigned __int128) __X * __Y; + *__P = (unsigned long long) (__res >> 64); + return (unsigned long long) __res; +} + +#else /* !__x86_64__ */ + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mulx_u32 (unsigned int __X, unsigned int __Y, unsigned int *__P) +{ + unsigned long long __res = (unsigned long long) __X * __Y; + *__P = (unsigned int) (__res >> 32); + return (unsigned int) __res; +} + +#endif /* !__x86_64__ */ + +#ifdef __DISABLE_BMI2__ +#undef __DISABLE_BMI2__ +#pragma GCC pop_options +#endif /* __DISABLE_BMI2__ */ + +#endif /* _BMI2INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/bmiintrin.h b/template/sysroot/include/bmiintrin.h new file mode 100644 index 0000000..227eade --- /dev/null +++ b/template/sysroot/include/bmiintrin.h @@ -0,0 +1,202 @@ +/* Copyright (C) 2010-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _BMIINTRIN_H_INCLUDED +#define _BMIINTRIN_H_INCLUDED + +#ifndef __BMI__ +#pragma GCC push_options +#pragma GCC target("bmi") +#define __DISABLE_BMI__ +#endif /* __BMI__ */ + +extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__tzcnt_u16 (unsigned short __X) +{ + return __builtin_ia32_tzcnt_u16 (__X); +} + +extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tzcnt_u16 (unsigned short __X) +{ + return __builtin_ia32_tzcnt_u16 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__andn_u32 (unsigned int __X, unsigned int __Y) +{ + return ~__X & __Y; +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_andn_u32 (unsigned int __X, unsigned int __Y) +{ + return __andn_u32 (__X, __Y); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bextr_u32 (unsigned int __X, unsigned int __Y) +{ + return __builtin_ia32_bextr_u32 (__X, __Y); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_bextr_u32 (unsigned int __X, unsigned int __Y, unsigned __Z) +{ + return __builtin_ia32_bextr_u32 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8))); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsi_u32 (unsigned int __X) +{ + return __X & -__X; +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsi_u32 (unsigned int __X) +{ + return __blsi_u32 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsmsk_u32 (unsigned int __X) +{ + return __X ^ (__X - 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsmsk_u32 (unsigned int __X) +{ + return __blsmsk_u32 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsr_u32 (unsigned int __X) +{ + return __X & (__X - 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsr_u32 (unsigned int __X) +{ + return __blsr_u32 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__tzcnt_u32 (unsigned int __X) +{ + return __builtin_ia32_tzcnt_u32 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tzcnt_u32 (unsigned int __X) +{ + return __builtin_ia32_tzcnt_u32 (__X); +} + + +#ifdef __x86_64__ +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__andn_u64 (unsigned long long __X, unsigned long long __Y) +{ + return ~__X & __Y; +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_andn_u64 (unsigned long long __X, unsigned long long __Y) +{ + return __andn_u64 (__X, __Y); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bextr_u64 (unsigned long long __X, unsigned long long __Y) +{ + return __builtin_ia32_bextr_u64 (__X, __Y); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_bextr_u64 (unsigned long long __X, unsigned int __Y, unsigned int __Z) +{ + return __builtin_ia32_bextr_u64 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8))); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsi_u64 (unsigned long long __X) +{ + return __X & -__X; +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsi_u64 (unsigned long long __X) +{ + return __blsi_u64 (__X); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsmsk_u64 (unsigned long long __X) +{ + return __X ^ (__X - 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsmsk_u64 (unsigned long long __X) +{ + return __blsmsk_u64 (__X); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsr_u64 (unsigned long long __X) +{ + return __X & (__X - 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_blsr_u64 (unsigned long long __X) +{ + return __blsr_u64 (__X); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__tzcnt_u64 (unsigned long long __X) +{ + return __builtin_ia32_tzcnt_u64 (__X); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tzcnt_u64 (unsigned long long __X) +{ + return __builtin_ia32_tzcnt_u64 (__X); +} + +#endif /* __x86_64__ */ + +#ifdef __DISABLE_BMI__ +#undef __DISABLE_BMI__ +#pragma GCC pop_options +#endif /* __DISABLE_BMI__ */ + +#endif /* _BMIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/bmmintrin.h b/template/sysroot/include/bmmintrin.h new file mode 100644 index 0000000..2ce675c --- /dev/null +++ b/template/sysroot/include/bmmintrin.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _BMMINTRIN_H_INCLUDED +#define _BMMINTRIN_H_INCLUDED + +# error "SSE5 instruction set removed from compiler" + +#endif /* _BMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/cet.h b/template/sysroot/include/cet.h new file mode 100644 index 0000000..00b19ec --- /dev/null +++ b/template/sysroot/include/cet.h @@ -0,0 +1,93 @@ +/* ELF program property for Intel CET. + Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . + */ + +/* Add x86 feature with IBT and/or SHSTK bits to ELF program property + if they are enabled. Otherwise, contents in this header file are + unused. Define _CET_ENDBR for assembly codes. _CET_ENDBR should be + placed unconditionally at the entrance of a function whose address + may be taken. */ + +#ifndef _CET_H_INCLUDED +#define _CET_H_INCLUDED + +#ifdef __ASSEMBLER__ + +# if defined __CET__ && (__CET__ & 1) != 0 +# ifdef __x86_64__ +# define _CET_ENDBR endbr64 +# else +# define _CET_ENDBR endbr32 +# endif +# else +# define _CET_ENDBR +# endif + +# ifdef __ELF__ +# ifdef __CET__ +# if (__CET__ & 1) != 0 +/* GNU_PROPERTY_X86_FEATURE_1_IBT. */ +# define __PROPERTY_IBT 0x1 +# else +# define __PROPERTY_IBT 0x0 +# endif + +# if (__CET__ & 2) != 0 +/* GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ +# define __PROPERTY_SHSTK 0x2 +# else +# define __PROPERTY_SHSTK 0x0 +# endif + +# define __PROPERTY_BITS (__PROPERTY_IBT | __PROPERTY_SHSTK) + +# ifdef __LP64__ +# define __PROPERTY_ALIGN 3 +# else +# define __PROPERTY_ALIGN 2 +# endif + + .pushsection ".note.gnu.property", "a" + .p2align __PROPERTY_ALIGN + .long 1f - 0f /* name length. */ + .long 4f - 1f /* data length. */ + /* NT_GNU_PROPERTY_TYPE_0. */ + .long 5 /* note type. */ +0: + .asciz "GNU" /* vendor name. */ +1: + .p2align __PROPERTY_ALIGN + /* GNU_PROPERTY_X86_FEATURE_1_AND. */ + .long 0xc0000002 /* pr_type. */ + .long 3f - 2f /* pr_datasz. */ +2: + /* GNU_PROPERTY_X86_FEATURE_1_XXX. */ + .long __PROPERTY_BITS +3: + .p2align __PROPERTY_ALIGN +4: + .popsection +# endif /* __CET__ */ +# endif /* __ELF__ */ +#endif /* __ASSEMBLER__ */ + +#endif /* _CET_H_INCLUDED */ diff --git a/template/sysroot/include/cetintrin.h b/template/sysroot/include/cetintrin.h new file mode 100644 index 0000000..545cb9c --- /dev/null +++ b/template/sysroot/include/cetintrin.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2015-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _CETINTRIN_H_INCLUDED +#define _CETINTRIN_H_INCLUDED + +#ifndef __SHSTK__ +#pragma GCC push_options +#pragma GCC target ("shstk") +#define __DISABLE_SHSTK__ +#endif /* __SHSTK__ */ + +#ifdef __x86_64__ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_get_ssp (void) +{ + return __builtin_ia32_rdsspq (); +} +#else +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_get_ssp (void) +{ + return __builtin_ia32_rdsspd (); +} +#endif + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_inc_ssp (unsigned int __B) +{ +#ifdef __x86_64__ + __builtin_ia32_incsspq ((unsigned long long) __B); +#else + __builtin_ia32_incsspd (__B); +#endif +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_saveprevssp (void) +{ + __builtin_ia32_saveprevssp (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rstorssp (void *__B) +{ + __builtin_ia32_rstorssp (__B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wrssd (unsigned int __B, void *__C) +{ + __builtin_ia32_wrssd (__B, __C); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wrssq (unsigned long long __B, void *__C) +{ + __builtin_ia32_wrssq (__B, __C); +} +#endif + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wrussd (unsigned int __B, void *__C) +{ + __builtin_ia32_wrussd (__B, __C); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wrussq (unsigned long long __B, void *__C) +{ + __builtin_ia32_wrussq (__B, __C); +} +#endif + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_setssbsy (void) +{ + __builtin_ia32_setssbsy (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_clrssbsy (void *__B) +{ + __builtin_ia32_clrssbsy (__B); +} + +#ifdef __DISABLE_SHSTK__ +#undef __DISABLE_SHSTK__ +#pragma GCC pop_options +#endif /* __DISABLE_SHSTK__ */ + +#endif /* _CETINTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/cfloat b/template/sysroot/include/cfloat new file mode 100644 index 0000000..38ff830 --- /dev/null +++ b/template/sysroot/include/cfloat @@ -0,0 +1,56 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cfloat + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c float.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CFLOAT +#define _GLIBCXX_CFLOAT 1 + +#if __cplusplus >= 201103L +# ifndef DECIMAL_DIG +# define DECIMAL_DIG __DECIMAL_DIG__ +# endif +# ifndef FLT_EVAL_METHOD +# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +# endif +#endif + +#endif diff --git a/template/sysroot/include/cldemoteintrin.h b/template/sysroot/include/cldemoteintrin.h new file mode 100644 index 0000000..048ec5e --- /dev/null +++ b/template/sysroot/include/cldemoteintrin.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _CLDEMOTE_H_INCLUDED +#define _CLDEMOTE_H_INCLUDED + +#ifndef __CLDEMOTE__ +#pragma GCC push_options +#pragma GCC target("cldemote") +#define __DISABLE_CLDEMOTE__ +#endif /* __CLDEMOTE__ */ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_cldemote (void *__A) +{ + __builtin_ia32_cldemote (__A); +} +#ifdef __DISABLE_CLDEMOTE__ +#undef __DISABLE_CLDEMOTE__ +#pragma GCC pop_options +#endif /* __DISABLE_CLDEMOTE__ */ + +#endif /* _CLDEMOTE_H_INCLUDED */ diff --git a/template/sysroot/include/clflushoptintrin.h b/template/sysroot/include/clflushoptintrin.h new file mode 100644 index 0000000..1d9f2c8 --- /dev/null +++ b/template/sysroot/include/clflushoptintrin.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _CLFLUSHOPTINTRIN_H_INCLUDED +#define _CLFLUSHOPTINTRIN_H_INCLUDED + +#ifndef __CLFLUSHOPT__ +#pragma GCC push_options +#pragma GCC target("clflushopt") +#define __DISABLE_CLFLUSHOPT__ +#endif /* __CLFLUSHOPT__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_clflushopt (void *__A) +{ + __builtin_ia32_clflushopt (__A); +} + +#ifdef __DISABLE_CLFLUSHOPT__ +#undef __DISABLE_CLFLUSHOPT__ +#pragma GCC pop_options +#endif /* __DISABLE_CLFLUSHOPT__ */ + +#endif /* _CLFLUSHOPTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/climits b/template/sysroot/include/climits new file mode 100644 index 0000000..7e374ef --- /dev/null +++ b/template/sysroot/include/climits @@ -0,0 +1,59 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/climits + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c limits.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CLIMITS +#define _GLIBCXX_CLIMITS 1 + +#ifndef LLONG_MIN +#define LLONG_MIN (-__LONG_LONG_MAX__ - 1) +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX __LONG_LONG_MAX__ +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif + +#endif diff --git a/template/sysroot/include/clwbintrin.h b/template/sysroot/include/clwbintrin.h new file mode 100644 index 0000000..ac5a68e --- /dev/null +++ b/template/sysroot/include/clwbintrin.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _CLWBINTRIN_H_INCLUDED +#define _CLWBINTRIN_H_INCLUDED + +#ifndef __CLWB__ +#pragma GCC push_options +#pragma GCC target("clwb") +#define __DISABLE_CLWB__ +#endif /* __CLWB__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_clwb (void *__A) +{ + __builtin_ia32_clwb (__A); +} + +#ifdef __DISABLE_CLWB__ +#undef __DISABLE_CLWB__ +#pragma GCC pop_options +#endif /* __DISABLE_CLWB__ */ + +#endif /* _CLWBINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/clzerointrin.h b/template/sysroot/include/clzerointrin.h new file mode 100644 index 0000000..4d1f2bc --- /dev/null +++ b/template/sysroot/include/clzerointrin.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _CLZEROINTRIN_H_INCLUDED +#define _CLZEROINTRIN_H_INCLUDED + +#ifndef __CLZERO__ +#pragma GCC push_options +#pragma GCC target("clzero") +#define __DISABLE_CLZERO__ +#endif /* __CLZERO__ */ + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_clzero (void * __I) +{ + __builtin_ia32_clzero (__I); +} + +#ifdef __DISABLE_CLZERO__ +#undef __DISABLE_CLZERO__ +#pragma GCC pop_options +#endif /* __DISABLE_CLZERO__ */ + +#endif /* _CLZEROINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/cmpccxaddintrin.h b/template/sysroot/include/cmpccxaddintrin.h new file mode 100644 index 0000000..39f368f --- /dev/null +++ b/template/sysroot/include/cmpccxaddintrin.h @@ -0,0 +1,89 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _CMPCCXADDINTRIN_H_INCLUDED +#define _CMPCCXADDINTRIN_H_INCLUDED + +#ifdef __x86_64__ + +#ifndef __CMPCCXADD__ +#pragma GCC push_options +#pragma GCC target("cmpccxadd") +#define __DISABLE_CMPCCXADD__ +#endif /* __CMPCCXADD__ */ + +typedef enum { + _CMPCCX_O, /* Overflow. */ + _CMPCCX_NO, /* No overflow. */ + _CMPCCX_B, /* Below. */ + _CMPCCX_NB, /* Not below. */ + _CMPCCX_Z, /* Zero. */ + _CMPCCX_NZ, /* Not zero. */ + _CMPCCX_BE, /* Below or equal. */ + _CMPCCX_NBE, /* Neither below nor equal. */ + _CMPCCX_S, /* Sign. */ + _CMPCCX_NS, /* No sign. */ + _CMPCCX_P, /* Parity. */ + _CMPCCX_NP, /* No parity. */ + _CMPCCX_L, /* Less. */ + _CMPCCX_NL, /* Not less. */ + _CMPCCX_LE, /* Less or equal. */ + _CMPCCX_NLE, /* Neither less nor equal. */ +} _CMPCCX_ENUM; + +#ifdef __OPTIMIZE__ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cmpccxadd_epi32 (int *__A, int __B, int __C, const _CMPCCX_ENUM __D) +{ + return __builtin_ia32_cmpccxadd (__A, __B, __C, __D); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_cmpccxadd_epi64 (long long *__A, long long __B, long long __C, + const _CMPCCX_ENUM __D) +{ + return __builtin_ia32_cmpccxadd64 (__A, __B, __C, __D); +} +#else +#define _cmpccxadd_epi32(A,B,C,D) \ + __builtin_ia32_cmpccxadd ((int *) (A), (int) (B), (int) (C), \ + (_CMPCCX_ENUM) (D)) +#define _cmpccxadd_epi64(A,B,C,D) \ + __builtin_ia32_cmpccxadd64 ((long long *) (A), (long long) (B), \ + (long long) (C), (_CMPCCX_ENUM) (D)) +#endif + +#ifdef __DISABLE_CMPCCXADD__ +#undef __DISABLE_CMPCCXADD__ +#pragma GCC pop_options +#endif /* __DISABLE_CMPCCXADD__ */ + +#endif + +#endif /* _CMPCCXADDINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/compare b/template/sysroot/include/compare new file mode 100644 index 0000000..686aa6d --- /dev/null +++ b/template/sysroot/include/compare @@ -0,0 +1,1258 @@ +// -*- C++ -*- operator<=> three-way comparison support. + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file compare + * This is a Standard C++ Library header. + */ + +#ifndef _COMPARE +#define _COMPARE + +#pragma GCC system_header + +#define __glibcxx_want_three_way_comparison +#include + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ + // [cmp.categories], comparison category types + + namespace __cmp_cat + { + using type = signed char; + + enum class _Ord : type { equivalent = 0, less = -1, greater = 1 }; + + enum class _Ncmp : type { _Unordered = 2 }; + + struct __unspec + { + consteval __unspec(__unspec*) noexcept { } + }; + } + + class partial_ordering + { + // less=0xff, equiv=0x00, greater=0x01, unordered=0x02 + __cmp_cat::type _M_value; + + constexpr explicit + partial_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + constexpr explicit + partial_ordering(__cmp_cat::_Ncmp __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + friend class weak_ordering; + friend class strong_ordering; + + public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + [[nodiscard]] + friend constexpr bool + operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + [[nodiscard]] + friend constexpr bool + operator==(partial_ordering, partial_ordering) noexcept = default; + + [[nodiscard]] + friend constexpr bool + operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == -1; } + + [[nodiscard]] + friend constexpr bool + operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 1; } + + [[nodiscard]] + friend constexpr bool + operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + [[nodiscard]] + friend constexpr bool + operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == 1; } + + [[nodiscard]] + friend constexpr bool + operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == -1; } + + [[nodiscard]] + friend constexpr bool + operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return 0 >= __v._M_value; } + + [[nodiscard]] + friend constexpr partial_ordering + operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + [[nodiscard]] + friend constexpr partial_ordering + operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept + { + if (__v._M_value & 1) + return partial_ordering(__cmp_cat::_Ord(-__v._M_value)); + else + return __v; + } + }; + + // valid values' definitions + inline constexpr partial_ordering + partial_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr partial_ordering + partial_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr partial_ordering + partial_ordering::greater(__cmp_cat::_Ord::greater); + + inline constexpr partial_ordering + partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered); + + class weak_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v)) + { } + + friend class strong_ordering; + + public: + // valid values + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + [[nodiscard]] + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + [[nodiscard]] + friend constexpr bool + operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + [[nodiscard]] + friend constexpr bool + operator==(weak_ordering, weak_ordering) noexcept = default; + + [[nodiscard]] + friend constexpr bool + operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + [[nodiscard]] + friend constexpr bool + operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + [[nodiscard]] + friend constexpr bool + operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + [[nodiscard]] + friend constexpr bool + operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + [[nodiscard]] + friend constexpr bool + operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 < __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 > __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 <= __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 >= __v._M_value; } + + [[nodiscard]] + friend constexpr weak_ordering + operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + [[nodiscard]] + friend constexpr weak_ordering + operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr weak_ordering + weak_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr weak_ordering + weak_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr weak_ordering + weak_ordering::greater(__cmp_cat::_Ord::greater); + + class strong_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + strong_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + public: + // valid values + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + [[nodiscard]] + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + [[nodiscard]] + constexpr operator weak_ordering() const noexcept + { return weak_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + [[nodiscard]] + friend constexpr bool + operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + [[nodiscard]] + friend constexpr bool + operator==(strong_ordering, strong_ordering) noexcept = default; + + [[nodiscard]] + friend constexpr bool + operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + [[nodiscard]] + friend constexpr bool + operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + [[nodiscard]] + friend constexpr bool + operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + [[nodiscard]] + friend constexpr bool + operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + [[nodiscard]] + friend constexpr bool + operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 < __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 > __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 <= __v._M_value; } + + [[nodiscard]] + friend constexpr bool + operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 >= __v._M_value; } + + [[nodiscard]] + friend constexpr strong_ordering + operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + [[nodiscard]] + friend constexpr strong_ordering + operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr strong_ordering + strong_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr strong_ordering + strong_ordering::equal(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::greater(__cmp_cat::_Ord::greater); + + + // named comparison functions + [[nodiscard]] + constexpr bool + is_eq(partial_ordering __cmp) noexcept + { return __cmp == 0; } + + [[nodiscard]] + constexpr bool + is_neq(partial_ordering __cmp) noexcept + { return __cmp != 0; } + + [[nodiscard]] + constexpr bool + is_lt (partial_ordering __cmp) noexcept + { return __cmp < 0; } + + [[nodiscard]] + constexpr bool + is_lteq(partial_ordering __cmp) noexcept + { return __cmp <= 0; } + + [[nodiscard]] + constexpr bool + is_gt (partial_ordering __cmp) noexcept + { return __cmp > 0; } + + [[nodiscard]] + constexpr bool + is_gteq(partial_ordering __cmp) noexcept + { return __cmp >= 0; } + + namespace __detail + { + template + inline constexpr unsigned __cmp_cat_id = 1; + template<> + inline constexpr unsigned __cmp_cat_id = 2; + template<> + inline constexpr unsigned __cmp_cat_id = 4; + template<> + inline constexpr unsigned __cmp_cat_id = 8; + + template + constexpr auto __common_cmp_cat() + { + constexpr unsigned __cats = (__cmp_cat_id<_Ts> | ...); + // If any Ti is not a comparison category type, U is void. + if constexpr (__cats & 1) + return; + // Otherwise, if at least one Ti is std::partial_ordering, + // U is std::partial_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return partial_ordering::equivalent; + // Otherwise, if at least one Ti is std::weak_ordering, + // U is std::weak_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return weak_ordering::equivalent; + // Otherwise, U is std::strong_ordering. + else + return strong_ordering::equivalent; + } + } // namespace __detail + + // [cmp.common], common comparison category type + template + struct common_comparison_category + { + using type = decltype(__detail::__common_cmp_cat<_Ts...>()); + }; + + // Partial specializations for one and zero argument cases. + + template + struct common_comparison_category<_Tp> + { using type = void; }; + + template<> + struct common_comparison_category + { using type = partial_ordering; }; + + template<> + struct common_comparison_category + { using type = weak_ordering; }; + + template<> + struct common_comparison_category + { using type = strong_ordering; }; + + template<> + struct common_comparison_category<> + { using type = strong_ordering; }; + + template + using common_comparison_category_t + = typename common_comparison_category<_Ts...>::type; + +#if __cpp_lib_three_way_comparison >= 201907L + // C++ >= 20 && impl_3way_comparison >= 201907 && lib_concepts + namespace __detail + { + template + concept __compares_as + = same_as, _Cat>; + } // namespace __detail + + // [cmp.concept], concept three_way_comparable + template + concept three_way_comparable + = __detail::__weakly_eq_cmp_with<_Tp, _Tp> + && __detail::__partially_ordered_with<_Tp, _Tp> + && requires(const remove_reference_t<_Tp>& __a, + const remove_reference_t<_Tp>& __b) + { + { __a <=> __b } -> __detail::__compares_as<_Cat>; + }; + + template + concept three_way_comparable_with + = three_way_comparable<_Tp, _Cat> + && three_way_comparable<_Up, _Cat> + && common_reference_with&, + const remove_reference_t<_Up>&> + && three_way_comparable< + common_reference_t&, + const remove_reference_t<_Up>&>, _Cat> + && __detail::__weakly_eq_cmp_with<_Tp, _Up> + && __detail::__partially_ordered_with<_Tp, _Up> + && requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) + { + { __t <=> __u } -> __detail::__compares_as<_Cat>; + { __u <=> __t } -> __detail::__compares_as<_Cat>; + }; + + namespace __detail + { + template + using __cmp3way_res_t + = decltype(std::declval<_Tp>() <=> std::declval<_Up>()); + + // Implementation of std::compare_three_way_result. + // It is undefined for a program to add specializations of + // std::compare_three_way_result, so the std::compare_three_way_result_t + // alias ignores std::compare_three_way_result and uses + // __detail::__cmp3way_res_impl directly instead. + template + struct __cmp3way_res_impl + { }; + + template + requires requires { typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; } + struct __cmp3way_res_impl<_Tp, _Up> + { + using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; + }; + } // namespace __detail + + /// [cmp.result], result of three-way comparison + template + struct compare_three_way_result + : __detail::__cmp3way_res_impl<_Tp, _Up> + { }; + + /// [cmp.result], result of three-way comparison + template + using compare_three_way_result_t + = typename __detail::__cmp3way_res_impl<_Tp, _Up>::type; + + namespace __detail + { + // BUILTIN-PTR-THREE-WAY(T, U) + // This determines whether t <=> u results in a call to a built-in + // operator<=> comparing pointers. It doesn't work for function pointers + // (PR 93628). + template + concept __3way_builtin_ptr_cmp + = requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && ! requires(_Tp&& __t, _Up&& __u) + { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); }; + } // namespace __detail + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks + + // [cmp.object], typename compare_three_way + struct compare_three_way + { + template + requires three_way_comparable_with<_Tp, _Up> + constexpr auto + operator() [[nodiscard]] (_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) + { + if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) + { + auto __pt = static_cast(__t); + auto __pu = static_cast(__u); + if (std::__is_constant_evaluated()) + return __pt <=> __pu; + auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt); + auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu); + return __it <=> __iu; + } + else + return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); + } + + using is_transparent = void; + }; + + /// @cond undocumented + // Namespace for helpers for the customization points. + namespace __compare + { + template + constexpr weak_ordering + __fp_weak_ordering(_Tp __e, _Tp __f) + { + // Returns an integer with the same sign as the argument, and magnitude + // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5 + auto __cat = [](_Tp __fp) -> int { + const int __sign = __builtin_signbit(__fp) ? -1 : 1; + if (__builtin_isnormal(__fp)) + return (__fp == 0 ? 1 : 3) * __sign; + if (__builtin_isnan(__fp)) + return 5 * __sign; + if (int __inf = __builtin_isinf_sign(__fp)) + return 4 * __inf; + return 2 * __sign; + }; + + auto __po = __e <=> __f; + if (is_lt(__po)) + return weak_ordering::less; + else if (is_gt(__po)) + return weak_ordering::greater; + else if (__po == partial_ordering::equivalent) + return weak_ordering::equivalent; + else // unordered, at least one argument is NaN + { + // return -1 for negative nan, +1 for positive nan, 0 otherwise. + auto __isnan_sign = [](_Tp __fp) -> int { + return __builtin_isnan(__fp) + ? __builtin_signbit(__fp) ? -1 : 1 + : 0; + }; + auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f); + if (is_eq(__ord)) + return weak_ordering::equivalent; + else if (is_lt(__ord)) + return weak_ordering::less; + else + return weak_ordering::greater; + } + } + + void strong_order() = delete; + + template + concept __adl_strong = requires(_Tp&& __t, _Up&& __u) + { + strong_ordering(strong_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + void weak_order() = delete; + + template + concept __adl_weak = requires(_Tp&& __t, _Up&& __u) + { + weak_ordering(weak_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + void partial_order() = delete; + + template + concept __adl_partial = requires(_Tp&& __t, _Up&& __u) + { + partial_ordering(partial_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c) + { + _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u))); + }; + + template + concept __strongly_ordered + = __adl_strong<_Tp, _Up> + || floating_point> + || __cmp3way; + + template + concept __decayed_same_as = same_as, decay_t<_Up>>; + + class _Strong_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_strong<_Tp, _Up>) + return noexcept(strong_ordering(strong_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + } + + friend class _Weak_order; + friend class _Strong_fallback; + + // Names for the supported floating-point representations. + enum class _Fp_fmt + { + _Binary16, _Binary32, _Binary64, _Binary128, // IEEE + _X86_80bit, // x86 80-bit extended precision + _M68k_80bit, // m68k 80-bit extended precision + _Dbldbl, // IBM 128-bit double-double + _Bfloat16, // std::bfloat16_t + }; + +#ifndef __cpp_using_enum + // XXX Remove these once 'using enum' support is ubiquitous. + static constexpr _Fp_fmt _Binary16 = _Fp_fmt::_Binary16; + static constexpr _Fp_fmt _Binary32 = _Fp_fmt::_Binary32; + static constexpr _Fp_fmt _Binary64 = _Fp_fmt::_Binary64; + static constexpr _Fp_fmt _Binary128 = _Fp_fmt::_Binary128; + static constexpr _Fp_fmt _X86_80bit = _Fp_fmt::_X86_80bit; + static constexpr _Fp_fmt _M68k_80bit = _Fp_fmt::_M68k_80bit; + static constexpr _Fp_fmt _Dbldbl = _Fp_fmt::_Dbldbl; + static constexpr _Fp_fmt _Bfloat16 = _Fp_fmt::_Bfloat16; +#endif + + // Identify the format used by a floating-point type. + template + static consteval _Fp_fmt + _S_fp_fmt() noexcept + { +#ifdef __cpp_using_enum + using enum _Fp_fmt; +#endif + + // Identify these formats first, then assume anything else is IEEE. + // N.B. ARM __fp16 alternative format can be handled as binary16. + +#ifdef __LONG_DOUBLE_IBM128__ + if constexpr (__is_same(_Tp, long double)) + return _Dbldbl; +#elif defined __LONG_DOUBLE_IEEE128__ && defined __SIZEOF_IBM128__ + if constexpr (__is_same(_Tp, __ibm128)) + return _Dbldbl; +#endif + +#if __LDBL_MANT_DIG__ == 64 + if constexpr (__is_same(_Tp, long double)) + return __LDBL_MIN_EXP__ == -16381 ? _X86_80bit : _M68k_80bit; +#endif +#ifdef __SIZEOF_FLOAT80__ + if constexpr (__is_same(_Tp, __float80)) + return _X86_80bit; +#endif +#ifdef __STDCPP_BFLOAT16_T__ + if constexpr (__is_same(_Tp, decltype(0.0bf16))) + return _Bfloat16; +#endif + + constexpr int __width = sizeof(_Tp) * __CHAR_BIT__; + + if constexpr (__width == 16) // IEEE binary16 (or ARM fp16). + return _Binary16; + else if constexpr (__width == 32) // IEEE binary32 + return _Binary32; + else if constexpr (__width == 64) // IEEE binary64 + return _Binary64; + else if constexpr (__width == 128) // IEEE binary128 + return _Binary128; + } + + // So we don't need to include and pollute the namespace. + using int64_t = __INT64_TYPE__; + using int32_t = __INT32_TYPE__; + using int16_t = __INT16_TYPE__; + using uint64_t = __UINT64_TYPE__; + using uint16_t = __UINT16_TYPE__; + + // Used to unpack floating-point types that do not fit into an integer. + template + struct _Int + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + uint64_t _M_lo; + _Tp _M_hi; +#else + _Tp _M_hi; + uint64_t _M_lo; +#endif + + constexpr explicit + _Int(_Tp __hi, uint64_t __lo) noexcept : _M_hi(__hi) + { _M_lo = __lo; } + + constexpr explicit + _Int(uint64_t __lo) noexcept : _M_hi(0) + { _M_lo = __lo; } + + constexpr bool operator==(const _Int&) const = default; + +#if defined __hppa__ || (defined __mips__ && !defined __mips_nan2008) + consteval _Int + operator<<(int __n) const noexcept + { + // XXX this assumes n >= 64, which is true for the use below. + return _Int(static_cast<_Tp>(_M_lo << (__n - 64)), 0); + } +#endif + + constexpr _Int& + operator^=(const _Int& __rhs) noexcept + { + _M_hi ^= __rhs._M_hi; + _M_lo ^= __rhs._M_lo; + return *this; + } + + constexpr strong_ordering + operator<=>(const _Int& __rhs) const noexcept + { + strong_ordering __cmp = _M_hi <=> __rhs._M_hi; + if (__cmp != strong_ordering::equal) + return __cmp; + return _M_lo <=> __rhs._M_lo; + } + }; + + template + static constexpr _Tp + _S_compl(_Tp __t) noexcept + { + constexpr int __width = sizeof(_Tp) * __CHAR_BIT__; + // Sign extend to get all ones or all zeros. + make_unsigned_t<_Tp> __sign = __t >> (__width - 1); + // If the sign bit was set, this flips all bits below it. + // This converts ones' complement to two's complement. + return __t ^ (__sign >> 1); + } + + // As above but works on both parts of _Int. + template + static constexpr _Int<_Tp> + _S_compl(_Int<_Tp> __t) noexcept + { + constexpr int __width = sizeof(_Tp) * __CHAR_BIT__; + make_unsigned_t<_Tp> __sign = __t._M_hi >> (__width - 1); + __t._M_hi ^= (__sign >> 1 ); + uint64_t __sign64 = (_Tp)__sign; + __t._M_lo ^= __sign64; + return __t; + } + + // Bit-cast a floating-point value to an unsigned integer. + template + constexpr static auto + _S_fp_bits(_Tp __val) noexcept + { + if constexpr (sizeof(_Tp) == sizeof(int64_t)) + return __builtin_bit_cast(int64_t, __val); + else if constexpr (sizeof(_Tp) == sizeof(int32_t)) + return __builtin_bit_cast(int32_t, __val); + else if constexpr (sizeof(_Tp) == sizeof(int16_t)) + return __builtin_bit_cast(int16_t, __val); + else + { +#ifdef __cpp_using_enum + using enum _Fp_fmt; +#endif + constexpr auto __fmt = _S_fp_fmt<_Tp>(); + if constexpr (__fmt == _X86_80bit || __fmt == _M68k_80bit) + { + if constexpr (sizeof(_Tp) == 3 * sizeof(int32_t)) + { + auto __ival = __builtin_bit_cast(_Int, __val); + return _Int(__ival._M_hi, __ival._M_lo); + } + else + { + auto __ival = __builtin_bit_cast(_Int, __val); + return _Int(__ival._M_hi, __ival._M_lo); + } + } + else if constexpr (sizeof(_Tp) == 2 * sizeof(int64_t)) + { +#if __SIZEOF_INT128__ + return __builtin_bit_cast(__int128, __val); +#else + return __builtin_bit_cast(_Int, __val); +#endif + } + else + static_assert(sizeof(_Tp) == sizeof(int64_t), + "unsupported floating-point type"); + } + } + + template + static constexpr strong_ordering + _S_fp_cmp(_Tp __x, _Tp __y) noexcept + { +#ifdef __vax__ + if (__builtin_isnan(__x) || __builtin_isnan(__y)) + { + int __ix = (bool) __builtin_isnan(__x); + int __iy = (bool) __builtin_isnan(__y); + __ix *= __builtin_signbit(__x) ? -1 : 1; + __iy *= __builtin_signbit(__y) ? -1 : 1; + return __ix <=> __iy; + } + else + return __builtin_bit_cast(strong_ordering, __x <=> __y); +#endif + + auto __ix = _S_fp_bits(__x); + auto __iy = _S_fp_bits(__y); + + if (__ix == __iy) + return strong_ordering::equal; // All bits are equal, we're done. + +#ifdef __cpp_using_enum + using enum _Fp_fmt; +#endif + constexpr auto __fmt = _S_fp_fmt<_Tp>(); + + if constexpr (__fmt == _Dbldbl) // double-double + { + // Unpack the double-double into two parts. + // We never inspect the low double as a double, cast to integer. + struct _Unpacked { double _M_hi; int64_t _M_lo; }; + auto __x2 = __builtin_bit_cast(_Unpacked, __x); + auto __y2 = __builtin_bit_cast(_Unpacked, __y); + + // Compare the high doubles first and use result if unequal. + auto __cmp = _S_fp_cmp(__x2._M_hi, __y2._M_hi); + if (__cmp != strong_ordering::equal) + return __cmp; + + // For NaN the low double is unused, so if the high doubles + // are the same NaN, we don't need to compare the low doubles. + if (__builtin_isnan(__x2._M_hi)) + return strong_ordering::equal; + // Similarly, if the low doubles are +zero or -zero (which is + // true for all infinities and some other values), we're done. + if (((__x2._M_lo | __y2._M_lo) & 0x7fffffffffffffffULL) == 0) + return strong_ordering::equal; + + // Otherwise, compare the low parts. + return _S_compl(__x2._M_lo) <=> _S_compl(__y2._M_lo); + } + else + { + if constexpr (__fmt == _M68k_80bit) + { + // For m68k the MSB of the significand is ignored for the + // greatest exponent, so either 0 or 1 is valid there. + // Set it before comparing, so that we never have 0 there. + constexpr uint16_t __maxexp = 0x7fff; + if ((__ix._M_hi & __maxexp) == __maxexp) + __ix._M_lo |= 1ull << 63; + if ((__iy._M_hi & __maxexp) == __maxexp) + __iy._M_lo |= 1ull << 63; + } + else + { +#if defined __hppa__ || (defined __mips__ && !defined __mips_nan2008) + // IEEE 754-1985 allowed the meaning of the quiet/signaling + // bit to be reversed. Flip that to give desired ordering. + if (__builtin_isnan(__x) && __builtin_isnan(__y)) + { + using _Int = decltype(__ix); + + constexpr int __nantype = __fmt == _Binary32 ? 22 + : __fmt == _Binary64 ? 51 + : __fmt == _Binary128 ? 111 + : -1; + constexpr _Int __bit = _Int(1) << __nantype; + __ix ^= __bit; + __iy ^= __bit; + } +#endif + } + return _S_compl(__ix) <=> _S_compl(__iy); + } + } + + public: + template _Up> + requires __strongly_ordered<_Tp, _Up> + constexpr strong_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (floating_point>) + return _S_fp_cmp(__e, __f); + else if constexpr (__adl_strong<_Tp, _Up>) + return strong_ordering(strong_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __weakly_ordered + = floating_point> + || __adl_weak<_Tp, _Up> + || __cmp3way + || __strongly_ordered<_Tp, _Up>; + + class _Weak_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_weak<_Tp, _Up>) + return noexcept(weak_ordering(weak_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_order; + friend class _Weak_fallback; + + public: + template _Up> + requires __weakly_ordered<_Tp, _Up> + constexpr weak_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (floating_point>) + return __compare::__fp_weak_ordering(__e, __f); + else if constexpr (__adl_weak<_Tp, _Up>) + return weak_ordering(weak_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __partially_ordered + = __adl_partial<_Tp, _Up> + || __cmp3way + || __weakly_ordered<_Tp, _Up>; + + class _Partial_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_partial<_Tp, _Up>) + return noexcept(partial_ordering(partial_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_fallback; + + public: + template _Up> + requires __partially_ordered<_Tp, _Up> + constexpr partial_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_partial<_Tp, _Up>) + return partial_ordering(partial_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u) + { + { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) } + -> convertible_to; + { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) } + -> convertible_to; + }; + + class _Strong_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template _Up> + requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr strong_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else // __op_eq_lt<_Tp, _Up> + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? strong_ordering::equal + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? strong_ordering::less + : strong_ordering::greater; + } + }; + + class _Weak_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template _Up> + requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr weak_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else // __op_eq_lt<_Tp, _Up> + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? weak_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? weak_ordering::less + : weak_ordering::greater; + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3465. compare_partial_order_fallback requires F < E + template + concept __op_eq_lt_lt = __op_eq_lt<_Tp, _Up> + && requires(_Tp&& __t, _Up&& __u) + { + { static_cast<_Up&&>(__u) < static_cast<_Tp&&>(__t) } + -> convertible_to; + }; + + class _Partial_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template _Up> + requires __partially_ordered<_Tp, _Up> || __op_eq_lt_lt<_Tp, _Up> + constexpr partial_ordering + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else // __op_eq_lt_lt<_Tp, _Up> + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? partial_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? partial_ordering::less + : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e) + ? partial_ordering::greater + : partial_ordering::unordered; + } + }; + } // namespace @endcond + + // [cmp.alg], comparison algorithms + + inline namespace _Cpo + { + inline constexpr __compare::_Strong_order strong_order{}; + + inline constexpr __compare::_Weak_order weak_order{}; + + inline constexpr __compare::_Partial_order partial_order{}; + + inline constexpr __compare::_Strong_fallback + compare_strong_order_fallback{}; + + inline constexpr __compare::_Weak_fallback + compare_weak_order_fallback{}; + + inline constexpr __compare::_Partial_fallback + compare_partial_order_fallback{}; + } + + /// @cond undocumented + namespace __detail + { + // [expos.only.func] synth-three-way + inline constexpr struct _Synth3way + { + template + static constexpr bool + _S_noexcept(const _Tp* __t = nullptr, const _Up* __u = nullptr) + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return noexcept(*__t <=> *__u); + else + return noexcept(*__t < *__u) && noexcept(*__u < *__t); + } + + template + [[nodiscard]] + constexpr auto + operator()(const _Tp& __t, const _Up& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + requires requires + { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return __t <=> __u; + else + { + if (__t < __u) + return weak_ordering::less; + else if (__u < __t) + return weak_ordering::greater; + else + return weak_ordering::equivalent; + } + } + } __synth3way = {}; + + // [expos.only.func] synth-three-way-result + template + using __synth3way_t + = decltype(__detail::__synth3way(std::declval<_Tp&>(), + std::declval<_Up&>())); + } // namespace __detail + /// @endcond +#endif // __cpp_lib_three_way_comparison >= 201907L +} // namespace std + +#endif // C++20 + +#endif // _COMPARE diff --git a/template/sysroot/include/concepts b/template/sysroot/include/concepts new file mode 100644 index 0000000..4f3e059 --- /dev/null +++ b/template/sysroot/include/concepts @@ -0,0 +1,389 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/concepts + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_CONCEPTS +#define _GLIBCXX_CONCEPTS 1 + +#pragma GCC system_header + +#define __glibcxx_want_concepts +#include + +#ifdef __cpp_lib_concepts // C++ >= 20 && concepts +/** + * @defgroup concepts Concepts + * @ingroup utilities + * + * Concepts for checking type requirements. + */ + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // [concepts.lang], language-related concepts + + namespace __detail + { + template + concept __same_as = std::is_same_v<_Tp, _Up>; + } // namespace __detail + + /// [concept.same], concept same_as + template + concept same_as + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + + namespace __detail + { + template + concept __different_from + = !same_as, remove_cvref_t<_Up>>; + } // namespace __detail + + /// [concept.derived], concept derived_from + template + concept derived_from = __is_base_of(_Base, _Derived) + && is_convertible_v; + + /// [concept.convertible], concept convertible_to + template + concept convertible_to = is_convertible_v<_From, _To> + && requires { static_cast<_To>(std::declval<_From>()); }; + + /// [concept.commonref], concept common_reference_with + template + concept common_reference_with + = same_as, common_reference_t<_Up, _Tp>> + && convertible_to<_Tp, common_reference_t<_Tp, _Up>> + && convertible_to<_Up, common_reference_t<_Tp, _Up>>; + + /// [concept.common], concept common_with + template + concept common_with + = same_as, common_type_t<_Up, _Tp>> + && requires { + static_cast>(std::declval<_Tp>()); + static_cast>(std::declval<_Up>()); + } + && common_reference_with, + add_lvalue_reference_t> + && common_reference_with>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; + + // [concepts.arithmetic], arithmetic concepts + + template + concept integral = is_integral_v<_Tp>; + + template + concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + + template + concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + + template + concept floating_point = is_floating_point_v<_Tp>; + + namespace __detail + { + template + using __cref = const remove_reference_t<_Tp>&; + + template + concept __class_or_enum + = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; + + template + constexpr bool __destructible_impl = false; + template + requires requires(_Tp& __t) { { __t.~_Tp() } noexcept; } + constexpr bool __destructible_impl<_Tp> = true; + + template + constexpr bool __destructible = __destructible_impl<_Tp>; + template + constexpr bool __destructible<_Tp&> = true; + template + constexpr bool __destructible<_Tp&&> = true; + template + constexpr bool __destructible<_Tp[_Nm]> = __destructible<_Tp>; + + } // namespace __detail + + /// [concept.assignable], concept assignable_from + template + concept assignable_from + = is_lvalue_reference_v<_Lhs> + && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>> + && requires(_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>; + }; + + /// [concept.destructible], concept destructible + template + concept destructible = __detail::__destructible<_Tp>; + + /// [concept.constructible], concept constructible_from + template + concept constructible_from + = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + + /// [concept.defaultinitializable], concept default_initializable + template + concept default_initializable = constructible_from<_Tp> + && requires + { + _Tp{}; + (void) ::new _Tp; + }; + + /// [concept.moveconstructible], concept move_constructible + template + concept move_constructible + = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; + + /// [concept.copyconstructible], concept copy_constructible + template + concept copy_constructible + = move_constructible<_Tp> + && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> + && constructible_from<_Tp, const _Tp&> && convertible_to + && constructible_from<_Tp, const _Tp> && convertible_to; + + // [concept.swappable], concept swappable + + namespace ranges + { + /// @cond undocumented + namespace __swap + { + template void swap(_Tp&, _Tp&) = delete; + + template + concept __adl_swap + = (std::__detail::__class_or_enum> + || std::__detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + struct _Swap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_swap<_Tp, _Up>) + return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); + else + return is_nothrow_move_constructible_v> + && is_nothrow_move_assignable_v>; + } + + public: + template + requires __adl_swap<_Tp, _Up> + || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp> + && move_constructible> + && assignable_from<_Tp, remove_reference_t<_Tp>>) + constexpr void + operator()(_Tp&& __t, _Up&& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_swap<_Tp, _Up>) + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + else + { + auto __tmp = static_cast&&>(__t); + __t = static_cast&&>(__u); + __u = static_cast&&>(__tmp); + } + } + + template + requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) { + __swap(__e1, __e2); + } + constexpr void + operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const + noexcept(noexcept(std::declval()(*__e1, *__e2))) + { + for (size_t __n = 0; __n < _Num; ++__n) + (*this)(__e1[__n], __e2[__n]); + } + }; + } // namespace __swap + /// @endcond + + inline namespace _Cpo { + inline constexpr __swap::_Swap swap{}; + } + } // namespace ranges + + template + concept swappable + = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; + + template + concept swappable_with = common_reference_with<_Tp, _Up> + && requires(_Tp&& __t, _Up&& __u) { + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t)); + }; + + // [concepts.object], Object concepts + + template + concept movable = is_object_v<_Tp> && move_constructible<_Tp> + && assignable_from<_Tp&, _Tp> && swappable<_Tp>; + + template + concept copyable = copy_constructible<_Tp> && movable<_Tp> + && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&> + && assignable_from<_Tp&, const _Tp>; + + template + concept semiregular = copyable<_Tp> && default_initializable<_Tp>; + + // [concepts.compare], comparison concepts + + // [concept.booleantestable], Boolean testability + namespace __detail + { + template + concept __boolean_testable_impl = convertible_to<_Tp, bool>; + + template + concept __boolean_testable + = __boolean_testable_impl<_Tp> + && requires(_Tp&& __t) + { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; + } // namespace __detail + + // [concept.equalitycomparable], concept equality_comparable + + namespace __detail + { + template + concept __weakly_eq_cmp_with + = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + } // namespace __detail + + template + concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>; + + template + concept equality_comparable_with + = equality_comparable<_Tp> && equality_comparable<_Up> + && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && equality_comparable, + __detail::__cref<_Up>>> + && __detail::__weakly_eq_cmp_with<_Tp, _Up>; + + namespace __detail + { + template + concept __partially_ordered_with + = requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + } // namespace __detail + + // [concept.totallyordered], concept totally_ordered + template + concept totally_ordered + = equality_comparable<_Tp> + && __detail::__partially_ordered_with<_Tp, _Tp>; + + template + concept totally_ordered_with + = totally_ordered<_Tp> && totally_ordered<_Up> + && equality_comparable_with<_Tp, _Up> + && totally_ordered, + __detail::__cref<_Up>>> + && __detail::__partially_ordered_with<_Tp, _Up>; + + template + concept regular = semiregular<_Tp> && equality_comparable<_Tp>; + + // [concepts.callable], callable concepts + + /// [concept.invocable], concept invocable + template + concept invocable = is_invocable_v<_Fn, _Args...>; + + /// [concept.regularinvocable], concept regular_invocable + template + concept regular_invocable = invocable<_Fn, _Args...>; + + /// [concept.predicate], concept predicate + template + concept predicate = regular_invocable<_Fn, _Args...> + && __detail::__boolean_testable>; + + /// [concept.relation], concept relation + template + concept relation + = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up> + && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>; + + /// [concept.equiv], concept equivalence_relation + template + concept equivalence_relation = relation<_Rel, _Tp, _Up>; + + /// [concept.strictweakorder], concept strict_weak_order + template + concept strict_weak_order = relation<_Rel, _Tp, _Up>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // __cpp_lib_concepts + +#endif /* _GLIBCXX_CONCEPTS */ diff --git a/template/sysroot/include/coroutine b/template/sysroot/include/coroutine new file mode 100644 index 0000000..908c117 --- /dev/null +++ b/template/sysroot/include/coroutine @@ -0,0 +1,361 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/coroutine + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_COROUTINE +#define _GLIBCXX_COROUTINE 1 + +#pragma GCC system_header + +#define __glibcxx_want_coroutine +#include + +#if !__cpp_impl_coroutine +# error "the header requires -fcoroutines" +#endif + +#ifdef __cpp_lib_coroutine // C++ >= 14 && impl_coroutine + +#include +#if __cplusplus > 201703L +# include +#endif + +#if !defined __cpp_lib_three_way_comparison +# include // for std::less +#endif + +/** + * @defgroup coroutines Coroutines + * + * Components for supporting coroutine implementations. + * + * @since C++20 (and since C++14 as a libstdc++ extension) + */ + +namespace std _GLIBCXX_VISIBILITY (default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + inline namespace __n4861 { + + // C++20 17.12.2 coroutine traits + /// [coroutine.traits] + /// [coroutine.traits.primary] + /// If _Result::promise_type is valid and denotes a type then the traits + /// have a single publicly accessible member, otherwise they are empty. + template + struct coroutine_traits; + + template + struct __coroutine_traits_impl {}; + + template +#if __cpp_concepts + requires requires { typename _Result::promise_type; } + struct __coroutine_traits_impl<_Result, void> +#else + struct __coroutine_traits_impl<_Result, + __void_t> +#endif + { + using promise_type = typename _Result::promise_type; + }; + + template + struct coroutine_traits : __coroutine_traits_impl<_Result> {}; + + // C++20 17.12.3 Class template coroutine_handle + /// [coroutine.handle] + template + struct coroutine_handle; + + template <> struct + coroutine_handle + { + public: + // [coroutine.handle.con], construct/reset + constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {} + + constexpr coroutine_handle(std::nullptr_t __h) noexcept + : _M_fr_ptr(__h) + {} + + coroutine_handle& operator=(std::nullptr_t) noexcept + { + _M_fr_ptr = nullptr; + return *this; + } + + public: + // [coroutine.handle.export.import], export/import + constexpr void* address() const noexcept { return _M_fr_ptr; } + + constexpr static coroutine_handle from_address(void* __a) noexcept + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + public: + // [coroutine.handle.observers], observers + constexpr explicit operator bool() const noexcept + { + return bool(_M_fr_ptr); + } + + bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } + + // [coroutine.handle.resumption], resumption + void operator()() const { resume(); } + + void resume() const { __builtin_coro_resume(_M_fr_ptr); } + + void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } + + protected: + void* _M_fr_ptr; + }; + + // [coroutine.handle.compare], comparison operators + + constexpr bool + operator==(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return __a.address() == __b.address(); + } + +#ifdef __cpp_lib_three_way_comparison + constexpr strong_ordering + operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return std::compare_three_way()(__a.address(), __b.address()); + } +#else + // These are to enable operation with std=c++14,17. + constexpr bool + operator!=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return !(__a == __b); + } + + constexpr bool + operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return less()(__a.address(), __b.address()); + } + + constexpr bool + operator>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return __b < __a; + } + + constexpr bool + operator<=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return !(__a > __b); + } + + constexpr bool + operator>=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { + return !(__a < __b); + } +#endif + + template + struct coroutine_handle + { + // [coroutine.handle.con], construct/reset + + constexpr coroutine_handle() noexcept { } + + constexpr coroutine_handle(nullptr_t) noexcept { } + + static coroutine_handle + from_promise(_Promise& __p) + { + coroutine_handle __self; + __self._M_fr_ptr + = __builtin_coro_promise((char*) &__p, __alignof(_Promise), true); + return __self; + } + + coroutine_handle& operator=(nullptr_t) noexcept + { + _M_fr_ptr = nullptr; + return *this; + } + + // [coroutine.handle.export.import], export/import + + constexpr void* address() const noexcept { return _M_fr_ptr; } + + constexpr static coroutine_handle from_address(void* __a) noexcept + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + // [coroutine.handle.conv], conversion + constexpr operator coroutine_handle<>() const noexcept + { return coroutine_handle<>::from_address(address()); } + + // [coroutine.handle.observers], observers + constexpr explicit operator bool() const noexcept + { + return bool(_M_fr_ptr); + } + + bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } + + // [coroutine.handle.resumption], resumption + void operator()() const { resume(); } + + void resume() const { __builtin_coro_resume(_M_fr_ptr); } + + void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } + + // [coroutine.handle.promise], promise access + _Promise& promise() const + { + void* __t + = __builtin_coro_promise (_M_fr_ptr, __alignof(_Promise), false); + return *static_cast<_Promise*>(__t); + } + + private: + void* _M_fr_ptr = nullptr; + }; + + /// [coroutine.noop] + struct noop_coroutine_promise + { + }; + + // 17.12.4.1 Class noop_coroutine_promise + /// [coroutine.promise.noop] + template <> + struct coroutine_handle + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3460. Unimplementable noop_coroutine_handle guarantees + // [coroutine.handle.noop.conv], conversion + constexpr operator coroutine_handle<>() const noexcept + { return coroutine_handle<>::from_address(address()); } + + // [coroutine.handle.noop.observers], observers + constexpr explicit operator bool() const noexcept { return true; } + + constexpr bool done() const noexcept { return false; } + + // [coroutine.handle.noop.resumption], resumption + void operator()() const noexcept {} + + void resume() const noexcept {} + + void destroy() const noexcept {} + + // [coroutine.handle.noop.promise], promise access + noop_coroutine_promise& promise() const noexcept + { return _S_fr.__p; } + + // [coroutine.handle.noop.address], address + constexpr void* address() const noexcept { return _M_fr_ptr; } + + private: + friend coroutine_handle noop_coroutine() noexcept; + + struct __frame + { + static void __dummy_resume_destroy() { } + + void (*__r)() = __dummy_resume_destroy; + void (*__d)() = __dummy_resume_destroy; + struct noop_coroutine_promise __p; + }; + + static __frame _S_fr; + + explicit coroutine_handle() noexcept = default; + + void* _M_fr_ptr = &_S_fr; + }; + + using noop_coroutine_handle = coroutine_handle; + + inline noop_coroutine_handle::__frame + noop_coroutine_handle::_S_fr{}; + + inline noop_coroutine_handle noop_coroutine() noexcept + { + return noop_coroutine_handle(); + } + + // 17.12.5 Trivial awaitables + /// [coroutine.trivial.awaitables] + struct suspend_always + { + constexpr bool await_ready() const noexcept { return false; } + + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + + constexpr void await_resume() const noexcept {} + }; + + struct suspend_never + { + constexpr bool await_ready() const noexcept { return true; } + + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + + constexpr void await_resume() const noexcept {} + }; + + } // namespace __n4861 + + template struct hash; + + template + struct hash> + { + size_t + operator()(const coroutine_handle<_Promise>& __h) const noexcept + { + return reinterpret_cast(__h.address()); + } + }; + + _GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_coroutine + +#endif // _GLIBCXX_COROUTINE diff --git a/template/sysroot/include/cpuid.h b/template/sysroot/include/cpuid.h new file mode 100644 index 0000000..efb05f9 --- /dev/null +++ b/template/sysroot/include/cpuid.h @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2007-2024 Free Software Foundation, Inc. + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * . + */ + +#ifndef _CPUID_H_INCLUDED +#define _CPUID_H_INCLUDED + +/* %ecx */ +#define bit_SSE3 (1 << 0) +#define bit_PCLMUL (1 << 1) +#define bit_LZCNT (1 << 5) +#define bit_SSSE3 (1 << 9) +#define bit_FMA (1 << 12) +#define bit_CMPXCHG16B (1 << 13) +#define bit_SSE4_1 (1 << 19) +#define bit_SSE4_2 (1 << 20) +#define bit_MOVBE (1 << 22) +#define bit_POPCNT (1 << 23) +#define bit_AES (1 << 25) +#define bit_XSAVE (1 << 26) +#define bit_OSXSAVE (1 << 27) +#define bit_AVX (1 << 28) +#define bit_F16C (1 << 29) +#define bit_RDRND (1 << 30) + +/* %edx */ +#define bit_CMPXCHG8B (1 << 8) +#define bit_CMOV (1 << 15) +#define bit_MMX (1 << 23) +#define bit_FXSAVE (1 << 24) +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +/* Extended Features (%eax == 0x80000001) */ +/* %ecx */ +#define bit_LAHF_LM (1 << 0) +#define bit_ABM (1 << 5) +#define bit_SSE4a (1 << 6) +#define bit_PRFCHW (1 << 8) +#define bit_XOP (1 << 11) +#define bit_LWP (1 << 15) +#define bit_FMA4 (1 << 16) +#define bit_TBM (1 << 21) +#define bit_MWAITX (1 << 29) + +/* %edx */ +#define bit_MMXEXT (1 << 22) +#define bit_LM (1 << 29) +#define bit_3DNOWP (1 << 30) +#define bit_3DNOW (1u << 31) + +/* %ebx */ +#define bit_CLZERO (1 << 0) +#define bit_WBNOINVD (1 << 9) + +/* Extended Features Leaf (%eax == 7, %ecx == 0) */ +/* %ebx */ +#define bit_FSGSBASE (1 << 0) +#define bit_SGX (1 << 2) +#define bit_BMI (1 << 3) +#define bit_HLE (1 << 4) +#define bit_AVX2 (1 << 5) +#define bit_BMI2 (1 << 8) +#define bit_RTM (1 << 11) +#define bit_AVX512F (1 << 16) +#define bit_AVX512DQ (1 << 17) +#define bit_RDSEED (1 << 18) +#define bit_ADX (1 << 19) +#define bit_AVX512IFMA (1 << 21) +#define bit_CLFLUSHOPT (1 << 23) +#define bit_CLWB (1 << 24) +#define bit_AVX512PF (1 << 26) +#define bit_AVX512ER (1 << 27) +#define bit_AVX512CD (1 << 28) +#define bit_SHA (1 << 29) +#define bit_AVX512BW (1 << 30) +#define bit_AVX512VL (1u << 31) + +/* %ecx */ +#define bit_PREFETCHWT1 (1 << 0) +#define bit_AVX512VBMI (1 << 1) +#define bit_PKU (1 << 3) +#define bit_OSPKE (1 << 4) +#define bit_WAITPKG (1 << 5) +#define bit_AVX512VBMI2 (1 << 6) +#define bit_SHSTK (1 << 7) +#define bit_GFNI (1 << 8) +#define bit_VAES (1 << 9) +#define bit_VPCLMULQDQ (1 << 10) +#define bit_AVX512VNNI (1 << 11) +#define bit_AVX512BITALG (1 << 12) +#define bit_AVX512VPOPCNTDQ (1 << 14) +#define bit_RDPID (1 << 22) +#define bit_KL (1 << 23) +#define bit_CLDEMOTE (1 << 25) +#define bit_MOVDIRI (1 << 27) +#define bit_MOVDIR64B (1 << 28) +#define bit_ENQCMD (1 << 29) + +/* %edx */ +#define bit_AVX5124VNNIW (1 << 2) +#define bit_AVX5124FMAPS (1 << 3) +#define bit_UINTR (1 << 5) +#define bit_AVX512VP2INTERSECT (1 << 8) +#define bit_SERIALIZE (1 << 14) +#define bit_TSXLDTRK (1 << 16) +#define bit_PCONFIG (1 << 18) +#define bit_IBT (1 << 20) +#define bit_AMX_BF16 (1 << 22) +#define bit_AVX512FP16 (1 << 23) +#define bit_AMX_TILE (1 << 24) +#define bit_AMX_INT8 (1 << 25) + +/* Extended Features Sub-leaf (%eax == 7, %ecx == 1) */ +/* %eax */ +#define bit_SHA512 (1 << 0) +#define bit_SM3 (1 << 1) +#define bit_SM4 (1 << 2) +#define bit_RAOINT (1 << 3) +#define bit_AVXVNNI (1 << 4) +#define bit_AVX512BF16 (1 << 5) +#define bit_CMPCCXADD (1 << 7) +#define bit_AMX_COMPLEX (1 << 8) +#define bit_AMX_FP16 (1 << 21) +#define bit_HRESET (1 << 22) +#define bit_AVXIFMA (1 << 23) + +/* %edx */ +#define bit_AVXVNNIINT8 (1 << 4) +#define bit_AVXNECONVERT (1 << 5) +#define bit_AVXVNNIINT16 (1 << 10) +#define bit_PREFETCHI (1 << 14) +#define bit_USER_MSR (1 << 15) +#define bit_AVX10 (1 << 19) +#define bit_APX_F (1 << 21) + +/* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */ +#define bit_XSAVEOPT (1 << 0) +#define bit_XSAVEC (1 << 1) +#define bit_XSAVES (1 << 3) + +/* PT sub leaf (%eax == 0x14, %ecx == 0) */ +/* %ebx */ +#define bit_PTWRITE (1 << 4) + +/* Keylocker leaf (%eax == 0x19) */ +/* %ebx */ +#define bit_AESKLE ( 1<<0 ) +#define bit_WIDEKL ( 1<<2 ) + +/* AVX10 sub leaf (%eax == 0x24) */ +/* %ebx */ +#define bit_AVX10_256 (1 << 17) +#define bit_AVX10_512 (1 << 18) + +/* Signatures for different CPU implementations as returned in uses + of cpuid with level 0. */ +#define signature_AMD_ebx 0x68747541 +#define signature_AMD_ecx 0x444d4163 +#define signature_AMD_edx 0x69746e65 + +#define signature_CENTAUR_ebx 0x746e6543 +#define signature_CENTAUR_ecx 0x736c7561 +#define signature_CENTAUR_edx 0x48727561 + +#define signature_CYRIX_ebx 0x69727943 +#define signature_CYRIX_ecx 0x64616574 +#define signature_CYRIX_edx 0x736e4978 + +#define signature_INTEL_ebx 0x756e6547 +#define signature_INTEL_ecx 0x6c65746e +#define signature_INTEL_edx 0x49656e69 + +#define signature_TM1_ebx 0x6e617254 +#define signature_TM1_ecx 0x55504361 +#define signature_TM1_edx 0x74656d73 + +#define signature_TM2_ebx 0x756e6547 +#define signature_TM2_ecx 0x3638784d +#define signature_TM2_edx 0x54656e69 + +#define signature_NSC_ebx 0x646f6547 +#define signature_NSC_ecx 0x43534e20 +#define signature_NSC_edx 0x79622065 + +#define signature_NEXGEN_ebx 0x4778654e +#define signature_NEXGEN_ecx 0x6e657669 +#define signature_NEXGEN_edx 0x72446e65 + +#define signature_RISE_ebx 0x65736952 +#define signature_RISE_ecx 0x65736952 +#define signature_RISE_edx 0x65736952 + +#define signature_SIS_ebx 0x20536953 +#define signature_SIS_ecx 0x20536953 +#define signature_SIS_edx 0x20536953 + +#define signature_UMC_ebx 0x20434d55 +#define signature_UMC_ecx 0x20434d55 +#define signature_UMC_edx 0x20434d55 + +#define signature_VIA_ebx 0x20414956 +#define signature_VIA_ecx 0x20414956 +#define signature_VIA_edx 0x20414956 + +#define signature_VORTEX_ebx 0x74726f56 +#define signature_VORTEX_ecx 0x436f5320 +#define signature_VORTEX_edx 0x36387865 + +#define signature_SHANGHAI_ebx 0x68532020 +#define signature_SHANGHAI_ecx 0x20206961 +#define signature_SHANGHAI_edx 0x68676e61 + +#ifndef __x86_64__ +/* At least one cpu (Winchip 2) does not set %ebx and %ecx + for cpuid leaf 1. Forcibly zero the two registers before + calling cpuid as a precaution. */ +#define __cpuid(level, a, b, c, d) \ + do { \ + if (__builtin_constant_p (level) && (level) != 1) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)); \ + else \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "1" (0), "2" (0)); \ + } while (0) +#else +#define __cpuid(level, a, b, c, d) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) +#endif + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) + + +/* Return highest supported input value for cpuid instruction. ext can + be either 0x0 or 0x80000000 to return highest supported value for + basic or extended cpuid information. Function returns 0 if cpuid + is not supported or whatever cpuid returns in eax register. If sig + pointer is non-null, then first four bytes of the signature + (as found in ebx register) are returned in location pointed by sig. */ + +static __inline unsigned int +__get_cpuid_max (unsigned int __ext, unsigned int *__sig) +{ + unsigned int __eax, __ebx, __ecx, __edx; + +#ifndef __x86_64__ + /* See if we can use cpuid. On AMD64 we always can. */ +#if __GNUC__ >= 3 + __asm__ ("pushf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "mov{l}\t{%0, %1|%1, %0}\n\t" + "xor{l}\t{%2, %0|%0, %2}\n\t" + "push{l}\t%0\n\t" + "popf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "popf{l|d}\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#else +/* Host GCCs older than 3.0 weren't supporting Intel asm syntax + nor alternatives in i386 code. */ + __asm__ ("pushfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "movl\t%0, %1\n\t" + "xorl\t%2, %0\n\t" + "pushl\t%0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "popfl\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#endif + + if (__builtin_expect (!((__eax ^ __ebx) & 0x00200000), 0)) + return 0; +#endif + + /* Host supports cpuid. Return highest supported cpuid input value. */ + __cpuid (__ext, __eax, __ebx, __ecx, __edx); + + if (__sig) + *__sig = __ebx; + + return __eax; +} + +/* Return cpuid data for requested cpuid leaf, as found in returned + eax, ebx, ecx and edx registers. The function checks if cpuid is + supported and returns 1 for valid cpuid information or 0 for + unsupported cpuid leaf. All pointers are required to be non-null. */ + +static __inline int +__get_cpuid (unsigned int __leaf, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); + + if (__maxlevel == 0 || __maxlevel < __leaf) + return 0; + + __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} + +/* Same as above, but sub-leaf can be specified. */ + +static __inline int +__get_cpuid_count (unsigned int __leaf, unsigned int __subleaf, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); + + if (__builtin_expect (__maxlevel == 0, 0) || __maxlevel < __leaf) + return 0; + + __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} + +static __inline void +__cpuidex (int __cpuid_info[4], int __leaf, int __subleaf) +{ + __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1], + __cpuid_info[2], __cpuid_info[3]); +} + +#endif /* _CPUID_H_INCLUDED */ diff --git a/template/sysroot/include/cross-stdarg.h b/template/sysroot/include/cross-stdarg.h new file mode 100644 index 0000000..a695cfb --- /dev/null +++ b/template/sysroot/include/cross-stdarg.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2002-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef __CROSS_STDARG_H_INCLUDED +#define __CROSS_STDARG_H_INCLUDED + +/* Make sure that for non x64 targets cross builtins are defined. */ +#ifndef __x86_64__ +/* Call abi ms_abi. */ +#define __builtin_ms_va_list __builtin_va_list +#define __builtin_ms_va_copy __builtin_va_copy +#define __builtin_ms_va_start __builtin_va_start +#define __builtin_ms_va_end __builtin_va_end + +/* Call abi sysv_abi. */ +#define __builtin_sysv_va_list __builtin_va_list +#define __builtin_sysv_va_copy __builtin_va_copy +#define __builtin_sysv_va_start __builtin_va_start +#define __builtin_sysv_va_end __builtin_va_end +#endif + +#define __ms_va_copy(__d,__s) __builtin_ms_va_copy(__d,__s) +#define __ms_va_start(__v,__l) __builtin_ms_va_start(__v,__l) +#define __ms_va_arg(__v,__l) __builtin_va_arg(__v,__l) +#define __ms_va_end(__v) __builtin_ms_va_end(__v) + +#define __sysv_va_copy(__d,__s) __builtin_sysv_va_copy(__d,__s) +#define __sysv_va_start(__v,__l) __builtin_sysv_va_start(__v,__l) +#define __sysv_va_arg(__v,__l) __builtin_va_arg(__v,__l) +#define __sysv_va_end(__v) __builtin_sysv_va_end(__v) + +#ifndef __GNUC_SYSV_VA_LIST +#define __GNUC_SYSV_VA_LIST + typedef __builtin_sysv_va_list __gnuc_sysv_va_list; +#endif + +#ifndef _SYSV_VA_LIST_DEFINED +#define _SYSV_VA_LIST_DEFINED + typedef __gnuc_sysv_va_list sysv_va_list; +#endif + +#ifndef __GNUC_MS_VA_LIST +#define __GNUC_MS_VA_LIST + typedef __builtin_ms_va_list __gnuc_ms_va_list; +#endif + +#ifndef _MS_VA_LIST_DEFINED +#define _MS_VA_LIST_DEFINED + typedef __gnuc_ms_va_list ms_va_list; +#endif + +#endif /* __CROSS_STDARG_H_INCLUDED */ diff --git a/template/sysroot/include/cstdalign b/template/sysroot/include/cstdalign new file mode 100644 index 0000000..3b427cc --- /dev/null +++ b/template/sysroot/include/cstdalign @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdalign + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDALIGN +#define _GLIBCXX_CSTDALIGN 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDALIGN_H +# include +# endif +#endif + +#endif + diff --git a/template/sysroot/include/cstdarg b/template/sysroot/include/cstdarg new file mode 100644 index 0000000..ed5e050 --- /dev/null +++ b/template/sysroot/include/cstdarg @@ -0,0 +1,58 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdarg + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdarg.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#undef __need___va_list +#include +#include + +#ifndef _GLIBCXX_CSTDARG +#define _GLIBCXX_CSTDARG 1 + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef va_end +#define va_end(ap) va_end (ap) +#endif + +namespace std +{ + using ::va_list; +} // namespace std + +#endif diff --git a/template/sysroot/include/cstdbool b/template/sysroot/include/cstdbool new file mode 100644 index 0000000..f283546 --- /dev/null +++ b/template/sysroot/include/cstdbool @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdbool + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDBOOL +#define _GLIBCXX_CSTDBOOL 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDBOOL_H +# include +# endif +#endif + +#endif + diff --git a/template/sysroot/include/cstddef b/template/sysroot/include/cstddef new file mode 100644 index 0000000..b25a6b3 --- /dev/null +++ b/template/sysroot/include/cstddef @@ -0,0 +1,192 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cstddef + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stddef.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.1 Types +// + +#ifndef _GLIBCXX_CSTDDEF +#define _GLIBCXX_CSTDDEF 1 + +#pragma GCC system_header + +#undef __need_wchar_t +#undef __need_ptrdiff_t +#undef __need_size_t +#undef __need_NULL +#undef __need_wint_t +#include +#include + +#define __glibcxx_want_byte +#include + +extern "C++" +{ +#if __cplusplus >= 201103L +namespace std +{ + // We handle size_t, ptrdiff_t, and nullptr_t in c++config.h. + using ::max_align_t; +} +#endif // C++11 + +#ifdef __cpp_lib_byte // C++ >= 17 +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + /// std::byte + enum class byte : unsigned char {}; + + template struct __byte_operand { }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#ifdef _GLIBCXX_USE_CHAR8_T + template<> struct __byte_operand { using __type = byte; }; +#endif + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_0> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_1> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_2> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + + template + using __byte_op_t = typename __byte_operand<_IntegerType>::__type; + + template + [[__gnu__::__always_inline__]] + constexpr __byte_op_t<_IntegerType> + operator<<(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b << __shift); } + + template + [[__gnu__::__always_inline__]] + constexpr __byte_op_t<_IntegerType> + operator>>(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b >> __shift); } + + [[__gnu__::__always_inline__]] + constexpr byte + operator|(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l | (unsigned)__r); } + + [[__gnu__::__always_inline__]] + constexpr byte + operator&(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l & (unsigned)__r); } + + [[__gnu__::__always_inline__]] + constexpr byte + operator^(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l ^ (unsigned)__r); } + + [[__gnu__::__always_inline__]] + constexpr byte + operator~(byte __b) noexcept + { return (byte)(unsigned char)~(unsigned)__b; } + + template + [[__gnu__::__always_inline__]] + constexpr __byte_op_t<_IntegerType>& + operator<<=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b << __shift; } + + template + [[__gnu__::__always_inline__]] + constexpr __byte_op_t<_IntegerType>& + operator>>=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b >> __shift; } + + [[__gnu__::__always_inline__]] + constexpr byte& + operator|=(byte& __l, byte __r) noexcept + { return __l = __l | __r; } + + [[__gnu__::__always_inline__]] + constexpr byte& + operator&=(byte& __l, byte __r) noexcept + { return __l = __l & __r; } + + [[__gnu__::__always_inline__]] + constexpr byte& + operator^=(byte& __l, byte __r) noexcept + { return __l = __l ^ __r; } + + template + [[nodiscard,__gnu__::__always_inline__]] + constexpr _IntegerType + to_integer(__byte_op_t<_IntegerType> __b) noexcept + { return _IntegerType(__b); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __cpp_lib_byte +} // extern "C++" + +#endif // _GLIBCXX_CSTDDEF diff --git a/template/sysroot/include/cstdint b/template/sysroot/include/cstdint new file mode 100644 index 0000000..d31dc75 --- /dev/null +++ b/template/sysroot/include/cstdint @@ -0,0 +1,146 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdint + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CSTDINT +#define _GLIBCXX_CSTDINT 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#if ! _GLIBCXX_HOSTED && __has_include() +// For --disable-hosted-libstdcxx we want GCC's own stdint-gcc.h header +// even when -ffreestanding isn't used. +# include +#elif __has_include() +# include +#endif + +namespace std +{ +#ifdef _GLIBCXX_USE_C99_STDINT + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; + + using ::int_fast8_t; + using ::int_fast16_t; + using ::int_fast32_t; + using ::int_fast64_t; + + using ::int_least8_t; + using ::int_least16_t; + using ::int_least32_t; + using ::int_least64_t; + + using ::intmax_t; + using ::intptr_t; + + using ::uint8_t; + using ::uint16_t; + using ::uint32_t; + using ::uint64_t; + + using ::uint_fast8_t; + using ::uint_fast16_t; + using ::uint_fast32_t; + using ::uint_fast64_t; + + using ::uint_least8_t; + using ::uint_least16_t; + using ::uint_least32_t; + using ::uint_least64_t; + + using ::uintmax_t; + using ::uintptr_t; +#else // !_GLIBCXX_USE_C99_STDINT + + using intmax_t = __INTMAX_TYPE__; + using uintmax_t = __UINTMAX_TYPE__; + +#ifdef __INT8_TYPE__ + using int8_t = __INT8_TYPE__; +#endif +#ifdef __INT16_TYPE__ + using int16_t = __INT16_TYPE__; +#endif +#ifdef __INT32_TYPE__ + using int32_t = __INT32_TYPE__; +#endif +#ifdef __INT64_TYPE__ + using int64_t = __INT64_TYPE__; +#endif + + using int_least8_t = __INT_LEAST8_TYPE__; + using int_least16_t = __INT_LEAST16_TYPE__; + using int_least32_t = __INT_LEAST32_TYPE__; + using int_least64_t = __INT_LEAST64_TYPE__; + using int_fast8_t = __INT_FAST8_TYPE__; + using int_fast16_t = __INT_FAST16_TYPE__; + using int_fast32_t = __INT_FAST32_TYPE__; + using int_fast64_t = __INT_FAST64_TYPE__; + +#ifdef __INTPTR_TYPE__ + using intptr_t = __INTPTR_TYPE__; +#endif + +#ifdef __UINT8_TYPE__ + using uint8_t = __UINT8_TYPE__; +#endif +#ifdef __UINT16_TYPE__ + using uint16_t = __UINT16_TYPE__; +#endif +#ifdef __UINT32_TYPE__ + using uint32_t = __UINT32_TYPE__; +#endif +#ifdef __UINT64_TYPE__ + using uint64_t = __UINT64_TYPE__; +#endif + using uint_least8_t = __UINT_LEAST8_TYPE__; + using uint_least16_t = __UINT_LEAST16_TYPE__; + using uint_least32_t = __UINT_LEAST32_TYPE__; + using uint_least64_t = __UINT_LEAST64_TYPE__; + using uint_fast8_t = __UINT_FAST8_TYPE__; + using uint_fast16_t = __UINT_FAST16_TYPE__; + using uint_fast32_t = __UINT_FAST32_TYPE__; + using uint_fast64_t = __UINT_FAST64_TYPE__; +#ifdef __UINTPTR_TYPE__ + using uintptr_t = __UINTPTR_TYPE__; +#endif + +#endif // _GLIBCXX_USE_C99_STDINT +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_CSTDINT diff --git a/template/sysroot/include/cstdlib b/template/sysroot/include/cstdlib new file mode 100644 index 0000000..69e7a39 --- /dev/null +++ b/template/sysroot/include/cstdlib @@ -0,0 +1,279 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdlib + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdlib.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include + +#ifndef _GLIBCXX_CSTDLIB +#define _GLIBCXX_CSTDLIB 1 + +#if !_GLIBCXX_HOSTED +// The C standard does not require a freestanding implementation to +// provide . However, the C++ standard does still require +// -- but only the functionality mentioned in +// [lib.support.start.term]. + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#define NULL __null + +namespace std +{ + extern "C" void abort(void) _GLIBCXX_NOTHROW _GLIBCXX_NORETURN; + extern "C" int atexit(void (*)(void)) _GLIBCXX_NOTHROW; + extern "C" void exit(int) _GLIBCXX_NOTHROW _GLIBCXX_NORETURN; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + extern "C" int at_quick_exit(void (*)(void)) _GLIBCXX_NOTHROW; +# endif +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + extern "C" void quick_exit(int) _GLIBCXX_NOTHROW _GLIBCXX_NORETURN; +# endif +#if _GLIBCXX_USE_C99_STDLIB + extern "C" void _Exit(int) _GLIBCXX_NOTHROW _GLIBCXX_NORETURN; +#endif +#endif +} // namespace std + +#else + +// Need to ensure this finds the C library's not a libstdc++ +// wrapper that might already be installed later in the include search path. +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef abort +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# undef aligned_alloc +#endif +#undef atexit +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT +# undef at_quick_exit +# endif +#endif +#undef atof +#undef atoi +#undef atol +#undef bsearch +#undef calloc +#undef div +#undef exit +#undef free +#undef getenv +#undef labs +#undef ldiv +#undef malloc +#undef mblen +#undef mbstowcs +#undef mbtowc +#undef qsort +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT +# undef quick_exit +# endif +#endif +#undef rand +#undef realloc +#undef srand +#undef strtod +#undef strtol +#undef strtoul +#undef system +#undef wcstombs +#undef wctomb + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::div_t; + using ::ldiv_t; + + using ::abort; +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) + using ::aligned_alloc; +#endif + using ::atexit; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + using ::at_quick_exit; +# endif +#endif + using ::atof; + using ::atoi; + using ::atol; + using ::bsearch; + using ::calloc; + using ::div; + using ::exit; + using ::free; + using ::getenv; + using ::labs; + using ::ldiv; + using ::malloc; +#ifdef _GLIBCXX_HAVE_MBSTATE_T + using ::mblen; + using ::mbstowcs; + using ::mbtowc; +#endif // _GLIBCXX_HAVE_MBSTATE_T + using ::qsort; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + using ::quick_exit; +# endif +#endif + using ::rand; + using ::realloc; + using ::srand; + using ::strtod; + using ::strtol; + using ::strtoul; + using ::system; +#ifdef _GLIBCXX_USE_WCHAR_T + using ::wcstombs; + using ::wctomb; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline ldiv_t + div(long __i, long __j) _GLIBCXX_NOTHROW { return ldiv(__i, __j); } +#endif + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if _GLIBCXX_USE_C99_STDLIB + +#undef _Exit +#undef llabs +#undef lldiv +#undef atoll +#undef strtoll +#undef strtoull +#undef strtof +#undef strtold + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::lldiv_t; +#endif +#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC + extern "C" void (_Exit)(int) _GLIBCXX_NOTHROW _GLIBCXX_NORETURN; +#endif +#if !_GLIBCXX_USE_C99_DYNAMIC + using ::_Exit; +#endif + +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::llabs; + + inline lldiv_t + div(long long __n, long long __d) + { lldiv_t __q; __q.quot = __n / __d; __q.rem = __n % __d; return __q; } + + using ::lldiv; +#endif + +#if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + extern "C" long long int (atoll)(const char *) _GLIBCXX_NOTHROW; + extern "C" long long int + (strtoll)(const char * __restrict, char ** __restrict, int) _GLIBCXX_NOTHROW; + extern "C" unsigned long long int + (strtoull)(const char * __restrict, char ** __restrict, int) _GLIBCXX_NOTHROW; +#endif +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::atoll; + using ::strtoll; + using ::strtoull; +#endif + using ::strtof; + using ::strtold; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +namespace std +{ +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::__gnu_cxx::lldiv_t; +#endif + using ::__gnu_cxx::_Exit; +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::__gnu_cxx::llabs; + using ::__gnu_cxx::div; + using ::__gnu_cxx::lldiv; +#endif + using ::__gnu_cxx::atoll; + using ::__gnu_cxx::strtof; + using ::__gnu_cxx::strtoll; + using ::__gnu_cxx::strtoull; + using ::__gnu_cxx::strtold; +} // namespace std + +#else // ! _GLIBCXX_USE_C99_STDLIB + +// We also check for strtof and strtold separately from _GLIBCXX_USE_C99_STDLIB + +#if _GLIBCXX_HAVE_STRTOF +#undef strtof +namespace std { using ::strtof; } +#endif + +#if _GLIBCXX_HAVE_STRTOLD +#undef strtold +namespace std { using ::strtold; } +#endif + +#endif // _GLIBCXX_USE_C99_STDLIB + +} // extern "C++" + +#endif // !_GLIBCXX_HOSTED + +#endif diff --git a/template/sysroot/include/cxxabi.h b/template/sysroot/include/cxxabi.h new file mode 100644 index 0000000..d63eae6 --- /dev/null +++ b/template/sysroot/include/cxxabi.h @@ -0,0 +1,715 @@ +// ABI Support -*- C++ -*- + +// Copyright (C) 2000-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// Written by Nathan Sidwell, Codesourcery LLC, + +/* This file declares the new abi entry points into the runtime. It is not + normally necessary for user programs to include this header, or use the + entry points directly. However, this header is available should that be + needed. + + Some of the entry points are intended for both C and C++, thus this header + is includable from both C and C++. Though the C++ specific parts are not + available in C, naturally enough. */ + +/** @file cxxabi.h + * The header provides an interface to the C++ ABI. + */ + +#ifndef _CXXABI_H +#define _CXXABI_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +namespace __cxxabiv1 +{ + extern "C" + { +#endif + + typedef __cxa_cdtor_return_type (*__cxa_cdtor_type)(void *); + + // Allocate array. + void* + __cxa_vec_new(size_t __element_count, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __constructor, + __cxa_cdtor_type __destructor); + + void* + __cxa_vec_new2(size_t __element_count, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __constructor, + __cxa_cdtor_type __destructor, void *(*__alloc) (size_t), + void (*__dealloc) (void*)); + + void* + __cxa_vec_new3(size_t __element_count, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __constructor, + __cxa_cdtor_type __destructor, void *(*__alloc) (size_t), + void (*__dealloc) (void*, size_t)); + + // Construct array. + __cxa_vec_ctor_return_type + __cxa_vec_ctor(void* __array_address, size_t __element_count, + size_t __element_size, __cxa_cdtor_type __constructor, + __cxa_cdtor_type __destructor); + + __cxa_vec_ctor_return_type + __cxa_vec_cctor(void* __dest_array, void* __src_array, + size_t __element_count, size_t __element_size, + __cxa_cdtor_return_type (*__constructor) (void*, void*), + __cxa_cdtor_type __destructor); + + // Destruct array. + void + __cxa_vec_dtor(void* __array_address, size_t __element_count, + size_t __element_size, __cxa_cdtor_type __destructor); + + void + __cxa_vec_cleanup(void* __array_address, size_t __element_count, size_t __s, + __cxa_cdtor_type __destructor) _GLIBCXX_NOTHROW; + + // Destruct and release array. + void + __cxa_vec_delete(void* __array_address, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __destructor); + + void + __cxa_vec_delete2(void* __array_address, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __destructor, + void (*__dealloc) (void*)); + + void + __cxa_vec_delete3(void* __array_address, size_t __element_size, + size_t __padding_size, __cxa_cdtor_type __destructor, + void (*__dealloc) (void*, size_t)); + + int + __cxa_guard_acquire(__guard*); + + void + __cxa_guard_release(__guard*) _GLIBCXX_NOTHROW; + + void + __cxa_guard_abort(__guard*) _GLIBCXX_NOTHROW; + + // DSO destruction. + int +#ifdef _GLIBCXX_CDTOR_CALLABI + __cxa_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void*) _GLIBCXX_NOTHROW; +#else + __cxa_atexit(void (*)(void*), void*, void*) _GLIBCXX_NOTHROW; +#endif + + void + __cxa_finalize(void*); + + // TLS destruction. + int +#ifdef _GLIBCXX_CDTOR_CALLABI + __cxa_thread_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void *) _GLIBCXX_NOTHROW; +#else + __cxa_thread_atexit(void (*)(void*), void*, void *) _GLIBCXX_NOTHROW; +#endif + + // Pure virtual functions. + void + __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); + + void + __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); + + // Exception handling auxiliary. + void + __cxa_bad_cast() __attribute__((__noreturn__)); + + void + __cxa_bad_typeid() __attribute__((__noreturn__)); + + void + __cxa_throw_bad_array_new_length() __attribute__((__noreturn__)); + + /** + * @brief Demangling routine. + * ABI-mandated entry point in the C++ runtime library for demangling. + * + * @param __mangled_name A NUL-terminated character string + * containing the name to be demangled. + * + * @param __output_buffer A region of memory, allocated with + * malloc, of @a *__length bytes, into which the demangled name is + * stored. If @a __output_buffer is not long enough, it is + * expanded using realloc. @a __output_buffer may instead be null; + * in that case, the demangled name is placed in a region of memory + * allocated with malloc. + * + * @param __length If @a __length is non-null, the length of the + * buffer containing the demangled name is placed in @a *__length. + * + * @param __status If @a __status is non-null, @a *__status is set to + * one of the following values: + * 0: The demangling operation succeeded. + * -1: A memory allocation failure occurred. + * -2: @a mangled_name is not a valid name under the C++ ABI mangling rules. + * -3: One of the arguments is invalid. + * + * @return A pointer to the start of the NUL-terminated demangled + * name, or a null pointer if the demangling fails. The caller is + * responsible for deallocating this memory using @c free. + * + * The demangling is performed using the C++ ABI mangling rules, + * with GNU extensions. For example, this function is used in + * __gnu_cxx::__verbose_terminate_handler. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html + * for other examples of use. + * + * @note The same demangling functionality is available via + * libiberty (@c and @c libiberty.a) in GCC + * 3.1 and later, but that requires explicit installation (@c + * --enable-install-libiberty) and uses a different API, although + * the ABI is unchanged. + */ + char* + __cxa_demangle(const char* __mangled_name, char* __output_buffer, + size_t* __length, int* __status); + +#ifdef __cplusplus + } +} // namespace __cxxabiv1 +#endif + +#ifdef __cplusplus + +#include + +namespace __cxxabiv1 +{ + // Type information for int, float etc. + class __fundamental_type_info : public std::type_info + { + public: + explicit + __fundamental_type_info(const char* __n) : std::type_info(__n) { } + + virtual + ~__fundamental_type_info(); + }; + + // Type information for array objects. + class __array_type_info : public std::type_info + { + public: + explicit + __array_type_info(const char* __n) : std::type_info(__n) { } + + virtual + ~__array_type_info(); + }; + + // Type information for functions (both member and non-member). + class __function_type_info : public std::type_info + { + public: + explicit + __function_type_info(const char* __n) : std::type_info(__n) { } + + virtual + ~__function_type_info(); + + protected: + // Implementation defined member function. + virtual bool + __is_function_p() const; + }; + + // Type information for enumerations. + class __enum_type_info : public std::type_info + { + public: + explicit + __enum_type_info(const char* __n) : std::type_info(__n) { } + + virtual + ~__enum_type_info(); + }; + + // Common type information for simple pointers and pointers to member. + class __pbase_type_info : public std::type_info + { + public: + unsigned int __flags; // Qualification of the target object. + const std::type_info* __pointee; // Type of pointed to object. + + explicit + __pbase_type_info(const char* __n, int __quals, + const std::type_info* __type) + : std::type_info(__n), __flags(__quals), __pointee(__type) + { } + + virtual + ~__pbase_type_info(); + + // Implementation defined type. + enum __masks + { + __const_mask = 0x1, + __volatile_mask = 0x2, + __restrict_mask = 0x4, + __incomplete_mask = 0x8, + __incomplete_class_mask = 0x10, + __transaction_safe_mask = 0x20, + __noexcept_mask = 0x40 + }; + + protected: + __pbase_type_info(const __pbase_type_info&); + + __pbase_type_info& + operator=(const __pbase_type_info&); + + // Implementation defined member functions. + virtual bool + __do_catch(const std::type_info* __thr_type, void** __thr_obj, + unsigned int __outer) const; + + inline virtual bool + __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj, + unsigned __outer) const; + }; + + inline bool __pbase_type_info:: + __pointer_catch (const __pbase_type_info *thrown_type, + void **thr_obj, + unsigned outer) const + { + return __pointee->__do_catch (thrown_type->__pointee, thr_obj, outer + 2); + } + + // Type information for simple pointers. + class __pointer_type_info : public __pbase_type_info + { + public: + explicit + __pointer_type_info(const char* __n, int __quals, + const std::type_info* __type) + : __pbase_type_info (__n, __quals, __type) { } + + + virtual + ~__pointer_type_info(); + + protected: + // Implementation defined member functions. + virtual bool + __is_pointer_p() const; + + virtual bool + __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj, + unsigned __outer) const; + }; + + class __class_type_info; + + // Type information for a pointer to member variable. + class __pointer_to_member_type_info : public __pbase_type_info + { + public: + __class_type_info* __context; // Class of the member. + + explicit + __pointer_to_member_type_info(const char* __n, int __quals, + const std::type_info* __type, + __class_type_info* __klass) + : __pbase_type_info(__n, __quals, __type), __context(__klass) { } + + virtual + ~__pointer_to_member_type_info(); + + protected: + __pointer_to_member_type_info(const __pointer_to_member_type_info&); + + __pointer_to_member_type_info& + operator=(const __pointer_to_member_type_info&); + + // Implementation defined member function. + virtual bool + __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj, + unsigned __outer) const; + }; + + // Helper class for __vmi_class_type. + class __base_class_type_info + { + public: + const __class_type_info* __base_type; // Base class type. +#ifdef _GLIBCXX_LLP64 + long long __offset_flags; // Offset and info. +#else + long __offset_flags; // Offset and info. +#endif + + enum __offset_flags_masks + { + __virtual_mask = 0x1, + __public_mask = 0x2, + __hwm_bit = 2, + __offset_shift = 8 // Bits to shift offset. + }; + + // Implementation defined member functions. + bool + __is_virtual_p() const + { return __offset_flags & __virtual_mask; } + + bool + __is_public_p() const + { return __offset_flags & __public_mask; } + + ptrdiff_t + __offset() const + { + // This shift, being of a signed type, is implementation + // defined. GCC implements such shifts as arithmetic, which is + // what we want. + return static_cast(__offset_flags) >> __offset_shift; + } + }; + + // Type information for a class. + class __class_type_info : public std::type_info + { + public: + explicit + __class_type_info (const char *__n) : type_info(__n) { } + + virtual + ~__class_type_info (); + + // Implementation defined types. + // The type sub_kind tells us about how a base object is contained + // within a derived object. We often do this lazily, hence the + // UNKNOWN value. At other times we may use NOT_CONTAINED to mean + // not publicly contained. + enum __sub_kind + { + // We have no idea. + __unknown = 0, + + // Not contained within us (in some circumstances this might + // mean not contained publicly) + __not_contained, + + // Contained ambiguously. + __contained_ambig, + + // Via a virtual path. + __contained_virtual_mask = __base_class_type_info::__virtual_mask, + + // Via a public path. + __contained_public_mask = __base_class_type_info::__public_mask, + + // Contained within us. + __contained_mask = 1 << __base_class_type_info::__hwm_bit, + + __contained_private = __contained_mask, + __contained_public = __contained_mask | __contained_public_mask + }; + + struct __upcast_result; + struct __dyncast_result; + + protected: + // Implementation defined member functions. + virtual bool + __do_upcast(const __class_type_info* __dst_type, void**__obj_ptr) const; + + virtual bool + __do_catch(const type_info* __thr_type, void** __thr_obj, + unsigned __outer) const; + + public: + // Helper for upcast. See if DST is us, or one of our bases. + // Return false if not found, true if found. + virtual bool + __do_upcast(const __class_type_info* __dst, const void* __obj, + __upcast_result& __restrict __result) const; + + // Indicate whether SRC_PTR of type SRC_TYPE is contained publicly + // within OBJ_PTR. OBJ_PTR points to a base object of our type, + // which is the destination type. SRC2DST indicates how SRC + // objects might be contained within this type. If SRC_PTR is one + // of our SRC_TYPE bases, indicate the virtuality. Returns + // not_contained for non containment or private containment. + inline __sub_kind + __find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr, + const __class_type_info* __src_type, + const void* __src_ptr) const; + + // Helper for dynamic cast. ACCESS_PATH gives the access from the + // most derived object to this base. DST_TYPE indicates the + // desired type we want. OBJ_PTR points to a base of our type + // within the complete object. SRC_TYPE indicates the static type + // started from and SRC_PTR points to that base within the most + // derived object. Fill in RESULT with what we find. Return true + // if we have located an ambiguous match. + virtual bool + __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path, + const __class_type_info* __dst_type, const void* __obj_ptr, + const __class_type_info* __src_type, const void* __src_ptr, + __dyncast_result& __result) const; + + // Helper for find_public_subobj. SRC2DST indicates how SRC_TYPE + // bases are inherited by the type started from -- which is not + // necessarily the current type. The current type will be a base + // of the destination type. OBJ_PTR points to the current base. + virtual __sub_kind + __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr, + const __class_type_info* __src_type, + const void* __src_ptr) const; + }; + + // Type information for a class with a single non-virtual base. + class __si_class_type_info : public __class_type_info + { + public: + const __class_type_info* __base_type; + + explicit + __si_class_type_info(const char *__n, const __class_type_info *__base) + : __class_type_info(__n), __base_type(__base) { } + + virtual + ~__si_class_type_info(); + + protected: + __si_class_type_info(const __si_class_type_info&); + + __si_class_type_info& + operator=(const __si_class_type_info&); + + // Implementation defined member functions. + virtual bool + __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path, + const __class_type_info* __dst_type, const void* __obj_ptr, + const __class_type_info* __src_type, const void* __src_ptr, + __dyncast_result& __result) const; + + virtual __sub_kind + __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr, + const __class_type_info* __src_type, + const void* __sub_ptr) const; + + virtual bool + __do_upcast(const __class_type_info*__dst, const void*__obj, + __upcast_result& __restrict __result) const; + }; + + // Type information for a class with multiple and/or virtual bases. + class __vmi_class_type_info : public __class_type_info + { + public: + unsigned int __flags; // Details about the class hierarchy. + unsigned int __base_count; // Number of direct bases. + + // The array of bases uses the trailing array struct hack so this + // class is not constructable with a normal constructor. It is + // internally generated by the compiler. + __base_class_type_info __base_info[1]; // Array of bases. + + explicit + __vmi_class_type_info(const char* __n, int ___flags) + : __class_type_info(__n), __flags(___flags), __base_count(0) { } + + virtual + ~__vmi_class_type_info(); + + // Implementation defined types. + enum __flags_masks + { + __non_diamond_repeat_mask = 0x1, // Distinct instance of repeated base. + __diamond_shaped_mask = 0x2, // Diamond shaped multiple inheritance. + __flags_unknown_mask = 0x10 + }; + + protected: + // Implementation defined member functions. + virtual bool + __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path, + const __class_type_info* __dst_type, const void* __obj_ptr, + const __class_type_info* __src_type, const void* __src_ptr, + __dyncast_result& __result) const; + + virtual __sub_kind + __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr, + const __class_type_info* __src_type, + const void* __src_ptr) const; + + virtual bool + __do_upcast(const __class_type_info* __dst, const void* __obj, + __upcast_result& __restrict __result) const; + }; + + // Exception handling forward declarations. + struct __cxa_exception; + struct __cxa_refcounted_exception; + struct __cxa_dependent_exception; + struct __cxa_eh_globals; + + extern "C" + { + // Dynamic cast runtime. + + // src2dst has the following possible values + // >-1: src_type is a unique public non-virtual base of dst_type + // dst_ptr + src2dst == src_ptr + // -1: unspecified relationship + // -2: src_type is not a public base of dst_type + // -3: src_type is a multiple public non-virtual base of dst_type + void* + __dynamic_cast(const void* __src_ptr, // Starting object. + const __class_type_info* __src_type, // Static type of object. + const __class_type_info* __dst_type, // Desired target type. + ptrdiff_t __src2dst); // How src and dst are related. + + + // Exception handling runtime. + + // The __cxa_eh_globals for the current thread can be obtained by using + // either of the following functions. The "fast" version assumes at least + // one prior call of __cxa_get_globals has been made from the current + // thread, so no initialization is necessary. + __cxa_eh_globals* + __cxa_get_globals() _GLIBCXX_NOTHROW __attribute__ ((__const__)); + + __cxa_eh_globals* + __cxa_get_globals_fast() _GLIBCXX_NOTHROW __attribute__ ((__const__)); + + // Free the space allocated for the primary exception. + void + __cxa_free_exception(void*) _GLIBCXX_NOTHROW; + + // Throw the exception. + void + __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *)) + __attribute__((__noreturn__)); + + // Used to implement exception handlers. + void* + __cxa_get_exception_ptr(void*) _GLIBCXX_NOTHROW __attribute__ ((__pure__)); + + void* + __cxa_begin_catch(void*) _GLIBCXX_NOTHROW; + + void + __cxa_end_catch(); + + void + __cxa_rethrow() __attribute__((__noreturn__)); + + // Returns the type_info for the currently handled exception [15.3/8], or + // null if there is none. + std::type_info* + __cxa_current_exception_type() _GLIBCXX_NOTHROW __attribute__ ((__pure__)); + + // GNU Extensions. + + // Allocate memory for a dependent exception. + __cxa_dependent_exception* + __cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW; + + // Free the space allocated for the dependent exception. + void + __cxa_free_dependent_exception(__cxa_dependent_exception*) _GLIBCXX_NOTHROW; + + } // extern "C" + + // A magic placeholder class that can be caught by reference + // to recognize foreign exceptions. + class __foreign_exception + { + virtual ~__foreign_exception() throw(); + virtual void __pure_dummy() = 0; // prevent catch by value + }; + +} // namespace __cxxabiv1 + +/** @namespace abi + * @brief The cross-vendor C++ Application Binary Interface. A + * namespace alias to __cxxabiv1, but user programs should use the + * alias 'abi'. + * + * A brief overview of an ABI is given in the libstdc++ FAQ, question + * 5.8 (you may have a copy of the FAQ locally, or you can view the online + * version at http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#5_8 ). + * + * GCC subscribes to a cross-vendor ABI for C++, sometimes + * called the IA64 ABI because it happens to be the native ABI for that + * platform. It is summarized at http://www.codesourcery.com/cxx-abi/ + * along with the current specification. + * + * For users of GCC greater than or equal to 3.x, entry points are + * available in , which notes, 'It is not normally + * necessary for user programs to include this header, or use the + * entry points directly. However, this header is available should + * that be needed.' +*/ +namespace abi = __cxxabiv1; + +namespace __gnu_cxx +{ + /** + * @brief Exception thrown by __cxa_guard_acquire. + * @ingroup exceptions + * + * C++ 2011 6.7 [stmt.dcl]/4: If control re-enters the declaration + * recursively while the variable is being initialized, the behavior + * is undefined. + * + * Since we already have a library function to handle locking, we might + * as well check for this situation and throw an exception. + * We use the second byte of the guard variable to remember that we're + * in the middle of an initialization. + */ + class recursive_init_error: public std::exception + { + public: + recursive_init_error() _GLIBCXX_NOTHROW; + virtual ~recursive_init_error() _GLIBCXX_NOTHROW; + }; +} +#endif // __cplusplus + +#pragma GCC visibility pop + +#endif // __CXXABI_H diff --git a/template/sysroot/include/debug/assertions.h b/template/sysroot/include/debug/assertions.h new file mode 100644 index 0000000..fff1ae8 --- /dev/null +++ b/template/sysroot/include/debug/assertions.h @@ -0,0 +1,68 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/assertions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H +#define _GLIBCXX_DEBUG_ASSERTIONS_H 1 + +#include + +#ifndef _GLIBCXX_ASSERTIONS +# define __glibcxx_requires_non_empty_range(_First,_Last) +# define __glibcxx_requires_nonempty() +# define __glibcxx_requires_subscript(_N) +#else + +// Verify that [_First, _Last) forms a non-empty iterator range. +# define __glibcxx_requires_non_empty_range(_First,_Last) \ + __glibcxx_assert(_First != _Last) +# define __glibcxx_requires_subscript(_N) \ + __glibcxx_assert(_N < this->size()) +// Verify that the container is nonempty +# define __glibcxx_requires_nonempty() \ + __glibcxx_assert(!this->empty()) +#endif + +#if defined _GLIBCXX_DEBUG && _GLIBCXX_HOSTED + +# define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition) + +# ifdef _GLIBCXX_DEBUG_PEDANTIC +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition) +# else +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# endif + +# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement + +#else +# define _GLIBCXX_DEBUG_ASSERT(_Condition) +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# define _GLIBCXX_DEBUG_ONLY(_Statement) +#endif + +#endif // _GLIBCXX_DEBUG_ASSERTIONS diff --git a/template/sysroot/include/debug/debug.h b/template/sysroot/include/debug/debug.h new file mode 100644 index 0000000..3d1f097 --- /dev/null +++ b/template/sysroot/include/debug/debug.h @@ -0,0 +1,145 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/debug.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H +#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1 + +/** Macros and namespaces used by the implementation outside of debug + * wrappers to verify certain properties. The __glibcxx_requires_xxx + * macros are merely wrappers around the __glibcxx_check_xxx wrappers + * when we are compiling with debug mode, but disappear when we are + * in release mode so that there is no checking performed in, e.g., + * the standard library algorithms. +*/ + +#include + +// Debug mode namespaces. + +/** + * @namespace std::__debug + * @brief GNU debug code, replaces standard behavior with debug behavior. + */ +namespace std +{ + namespace __debug { } +} + +/** @namespace __gnu_debug + * @brief GNU debug classes for public use. +*/ +namespace __gnu_debug +{ + using namespace std::__debug; + + template + struct _Safe_iterator; +} + +#if ! defined _GLIBCXX_DEBUG || ! _GLIBCXX_HOSTED + +# define __glibcxx_requires_cond(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) +# define __glibcxx_requires_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) + +#else + +# include + +# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) \ + __glibcxx_check_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) \ + __glibcxx_check_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) \ + __glibcxx_check_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \ + __glibcxx_check_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \ + __glibcxx_check_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ + __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \ + __glibcxx_check_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \ + __glibcxx_check_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) \ + __glibcxx_check_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ + __glibcxx_check_heap_pred(_First,_Last,_Pred) +# if __cplusplus < 201103L +# define __glibcxx_requires_string(_String) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != 0) +# define __glibcxx_requires_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) +# else +# define __glibcxx_requires_string(_String) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr) +# define __glibcxx_requires_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr || _Len == 0) +# endif +# define __glibcxx_requires_irreflexive(_First,_Last) \ + __glibcxx_check_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) \ + __glibcxx_check_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) + +# include + +#endif + +#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H diff --git a/template/sysroot/include/emmintrin.h b/template/sysroot/include/emmintrin.h new file mode 100644 index 0000000..915a523 --- /dev/null +++ b/template/sysroot/include/emmintrin.h @@ -0,0 +1,1608 @@ +/* Copyright (C) 2003-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 9.0. */ + +#ifndef _EMMINTRIN_H_INCLUDED +#define _EMMINTRIN_H_INCLUDED + +/* We need definitions from the SSE header files*/ +#include + +#ifndef __SSE2__ +#pragma GCC push_options +#pragma GCC target("sse2") +#define __DISABLE_SSE2__ +#endif /* __SSE2__ */ + +/* SSE2 */ +typedef double __v2df __attribute__ ((__vector_size__ (16))); +typedef long long __v2di __attribute__ ((__vector_size__ (16))); +typedef unsigned long long __v2du __attribute__ ((__vector_size__ (16))); +typedef int __v4si __attribute__ ((__vector_size__ (16))); +typedef unsigned int __v4su __attribute__ ((__vector_size__ (16))); +typedef short __v8hi __attribute__ ((__vector_size__ (16))); +typedef unsigned short __v8hu __attribute__ ((__vector_size__ (16))); +typedef char __v16qi __attribute__ ((__vector_size__ (16))); +typedef signed char __v16qs __attribute__ ((__vector_size__ (16))); +typedef unsigned char __v16qu __attribute__ ((__vector_size__ (16))); + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__)); + +/* Unaligned version of the same types. */ +typedef long long __m128i_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1))); +typedef double __m128d_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1))); + +/* Create a selector for use with the SHUFPD instruction. */ +#define _MM_SHUFFLE2(fp1,fp0) \ + (((fp1) << 1) | (fp0)) + +/* Create a vector with element 0 as F and the rest zero. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_sd (double __F) +{ + return __extension__ (__m128d){ __F, 0.0 }; +} + +/* Create a vector with both elements equal to F. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pd (double __F) +{ + return __extension__ (__m128d){ __F, __F }; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pd1 (double __F) +{ + return _mm_set1_pd (__F); +} + +/* Create a vector with the lower value X and upper value W. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pd (double __W, double __X) +{ + return __extension__ (__m128d){ __X, __W }; +} + +/* Create a vector with the lower value W and upper value X. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_pd (double __W, double __X) +{ + return __extension__ (__m128d){ __W, __X }; +} + +/* Create an undefined vector. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_undefined_pd (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128d __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +/* Create a vector of zeros. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_pd (void) +{ + return __extension__ (__m128d){ 0.0, 0.0 }; +} + +/* Sets the low DPFP value of A from the low value of B. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_move_sd (__m128d __A, __m128d __B) +{ + return __extension__ (__m128d) __builtin_shuffle ((__v2df)__A, (__v2df)__B, (__v2di){2, 1}); +} + +/* Load two DPFP values from P. The address must be 16-byte aligned. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_pd (double const *__P) +{ + return *(__m128d *)__P; +} + +/* Load two DPFP values from P. The address need not be 16-byte aligned. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_pd (double const *__P) +{ + return *(__m128d_u *)__P; +} + +/* Create a vector with all two elements equal to *P. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load1_pd (double const *__P) +{ + return _mm_set1_pd (*__P); +} + +/* Create a vector with element 0 as *P and the rest zero. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_sd (double const *__P) +{ + return _mm_set_sd (*__P); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_pd1 (double const *__P) +{ + return _mm_load1_pd (__P); +} + +/* Load two DPFP values in reverse order. The address must be aligned. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadr_pd (double const *__P) +{ + __m128d __tmp = _mm_load_pd (__P); + return __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,1)); +} + +/* Store two DPFP values. The address must be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_pd (double *__P, __m128d __A) +{ + *(__m128d *)__P = __A; +} + +/* Store two DPFP values. The address need not be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_pd (double *__P, __m128d __A) +{ + *(__m128d_u *)__P = __A; +} + +/* Stores the lower DPFP value. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_sd (double *__P, __m128d __A) +{ + *__P = ((__v2df)__A)[0]; +} + +extern __inline double __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_f64 (__m128d __A) +{ + return ((__v2df)__A)[0]; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storel_pd (double *__P, __m128d __A) +{ + _mm_store_sd (__P, __A); +} + +/* Stores the upper DPFP value. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeh_pd (double *__P, __m128d __A) +{ + *__P = ((__v2df)__A)[1]; +} + +/* Store the lower DPFP value across two words. + The address must be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store1_pd (double *__P, __m128d __A) +{ + _mm_store_pd (__P, __builtin_ia32_shufpd (__A, __A, _MM_SHUFFLE2 (0,0))); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_pd1 (double *__P, __m128d __A) +{ + _mm_store1_pd (__P, __A); +} + +/* Store two DPFP values in reverse order. The address must be aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storer_pd (double *__P, __m128d __A) +{ + _mm_store_pd (__P, __builtin_ia32_shufpd (__A, __A, _MM_SHUFFLE2 (0,1))); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi128_si32 (__m128i __A) +{ + return __builtin_ia32_vec_ext_v4si ((__v4si)__A, 0); +} + +#ifdef __x86_64__ +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi128_si64 (__m128i __A) +{ + return ((__v2di)__A)[0]; +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi128_si64x (__m128i __A) +{ + return ((__v2di)__A)[0]; +} +#endif + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_pd (__m128d __A, __m128d __B) +{ + return (__m128d) ((__v2df)__A + (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_addsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_pd (__m128d __A, __m128d __B) +{ + return (__m128d) ((__v2df)__A - (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_subsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_pd (__m128d __A, __m128d __B) +{ + return (__m128d) ((__v2df)__A * (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_mulsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_pd (__m128d __A, __m128d __B) +{ + return (__m128d) ((__v2df)__A / (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_divsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_pd (__m128d __A) +{ + return (__m128d)__builtin_ia32_sqrtpd ((__v2df)__A); +} + +/* Return pair {sqrt (B[0]), A[1]}. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_sd (__m128d __A, __m128d __B) +{ + __v2df __tmp = __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B); + return (__m128d)__builtin_ia32_sqrtsd ((__v2df)__tmp); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_minpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_minsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_maxpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_maxsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_and_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_andpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_andnot_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_andnpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_orpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_xorpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpeqpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpltpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmplepd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpgtpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpgepd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpneqpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnlt_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpnltpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnle_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpnlepd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpngt_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpngtpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnge_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpngepd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpord_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpordpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpunord_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpunordpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpeqsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpltsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmplesd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movsd ((__v2df) __A, + (__v2df) + __builtin_ia32_cmpltsd ((__v2df) __B, + (__v2df) + __A)); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movsd ((__v2df) __A, + (__v2df) + __builtin_ia32_cmplesd ((__v2df) __B, + (__v2df) + __A)); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpneqsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnlt_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpnltsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnle_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpnlesd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpngt_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movsd ((__v2df) __A, + (__v2df) + __builtin_ia32_cmpnltsd ((__v2df) __B, + (__v2df) + __A)); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnge_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movsd ((__v2df) __A, + (__v2df) + __builtin_ia32_cmpnlesd ((__v2df) __B, + (__v2df) + __A)); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpord_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpordsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpunord_sd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_cmpunordsd ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comieq_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdeq ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comilt_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdlt ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comile_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdle ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comigt_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdgt ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comige_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdge ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comineq_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_comisdneq ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomieq_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdeq ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomilt_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdlt ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomile_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdle ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomigt_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdgt ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomige_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdge ((__v2df)__A, (__v2df)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomineq_sd (__m128d __A, __m128d __B) +{ + return __builtin_ia32_ucomisdneq ((__v2df)__A, (__v2df)__B); +} + +/* Create a vector of Qi, where i is the element number. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_epi64x (long long __q1, long long __q0) +{ + return __extension__ (__m128i)(__v2di){ __q0, __q1 }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_epi64 (__m64 __q1, __m64 __q0) +{ + return _mm_set_epi64x ((long long)__q1, (long long)__q0); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_epi32 (int __q3, int __q2, int __q1, int __q0) +{ + return __extension__ (__m128i)(__v4si){ __q0, __q1, __q2, __q3 }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_epi16 (short __q7, short __q6, short __q5, short __q4, + short __q3, short __q2, short __q1, short __q0) +{ + return __extension__ (__m128i)(__v8hi){ + __q0, __q1, __q2, __q3, __q4, __q5, __q6, __q7 }; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_epi8 (char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) +{ + return __extension__ (__m128i)(__v16qi){ + __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07, + __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15 + }; +} + +/* Set all of the elements of the vector to A. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_epi64x (long long __A) +{ + return _mm_set_epi64x (__A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_epi64 (__m64 __A) +{ + return _mm_set_epi64 (__A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_epi32 (int __A) +{ + return _mm_set_epi32 (__A, __A, __A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_epi16 (short __A) +{ + return _mm_set_epi16 (__A, __A, __A, __A, __A, __A, __A, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_epi8 (char __A) +{ + return _mm_set_epi8 (__A, __A, __A, __A, __A, __A, __A, __A, + __A, __A, __A, __A, __A, __A, __A, __A); +} + +/* Create a vector of Qi, where i is the element number. + The parameter order is reversed from the _mm_set_epi* functions. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_epi64 (__m64 __q0, __m64 __q1) +{ + return _mm_set_epi64 (__q1, __q0); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_epi32 (int __q0, int __q1, int __q2, int __q3) +{ + return _mm_set_epi32 (__q3, __q2, __q1, __q0); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_epi16 (short __q0, short __q1, short __q2, short __q3, + short __q4, short __q5, short __q6, short __q7) +{ + return _mm_set_epi16 (__q7, __q6, __q5, __q4, __q3, __q2, __q1, __q0); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_epi8 (char __q00, char __q01, char __q02, char __q03, + char __q04, char __q05, char __q06, char __q07, + char __q08, char __q09, char __q10, char __q11, + char __q12, char __q13, char __q14, char __q15) +{ + return _mm_set_epi8 (__q15, __q14, __q13, __q12, __q11, __q10, __q09, __q08, + __q07, __q06, __q05, __q04, __q03, __q02, __q01, __q00); +} + +/* Create a vector with element 0 as *P and the rest zero. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_si128 (__m128i const *__P) +{ + return *__P; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_si128 (__m128i_u const *__P) +{ + return *__P; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadl_epi64 (__m128i_u const *__P) +{ + return _mm_set_epi64 ((__m64)0LL, *(__m64_u *)__P); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_si64 (void const *__P) +{ + return _mm_loadl_epi64 ((__m128i_u *)__P); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_si32 (void const *__P) +{ + return _mm_set_epi32 (0, 0, 0, (*(__m32_u *)__P)[0]); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_si16 (void const *__P) +{ + return _mm_set_epi16 (0, 0, 0, 0, 0, 0, 0, (*(__m16_u *)__P)[0]); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_si128 (__m128i *__P, __m128i __B) +{ + *__P = __B; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_si128 (__m128i_u *__P, __m128i __B) +{ + *__P = __B; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storel_epi64 (__m128i_u *__P, __m128i __B) +{ + *(__m64_u *)__P = (__m64) ((__v2di)__B)[0]; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_si64 (void *__P, __m128i __B) +{ + _mm_storel_epi64 ((__m128i_u *)__P, __B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_si32 (void *__P, __m128i __B) +{ + *(__m32_u *)__P = (__m32) ((__v4si)__B)[0]; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_si16 (void *__P, __m128i __B) +{ + *(__m16_u *)__P = (__m16) ((__v8hi)__B)[0]; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movepi64_pi64 (__m128i __B) +{ + return (__m64) ((__v2di)__B)[0]; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movpi64_epi64 (__m64 __A) +{ + return _mm_set_epi64 ((__m64)0LL, __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_move_epi64 (__m128i __A) +{ + return (__m128i)__builtin_ia32_movq128 ((__v2di) __A); +} + +/* Create an undefined vector. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_undefined_si128 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128i __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +/* Create a vector of zeros. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_si128 (void) +{ + return __extension__ (__m128i)(__v4si){ 0, 0, 0, 0 }; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_pd (__m128i __A) +{ + return (__m128d)__builtin_ia32_cvtdq2pd ((__v4si) __A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_ps (__m128i __A) +{ + return (__m128)__builtin_ia32_cvtdq2ps ((__v4si) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_epi32 (__m128d __A) +{ + return (__m128i)__builtin_ia32_cvtpd2dq ((__v2df) __A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_pi32 (__m128d __A) +{ + return (__m64)__builtin_ia32_cvtpd2pi ((__v2df) __A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpd_ps (__m128d __A) +{ + return (__m128)__builtin_ia32_cvtpd2ps ((__v2df) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttpd_epi32 (__m128d __A) +{ + return (__m128i)__builtin_ia32_cvttpd2dq ((__v2df) __A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttpd_pi32 (__m128d __A) +{ + return (__m64)__builtin_ia32_cvttpd2pi ((__v2df) __A); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpi32_pd (__m64 __A) +{ + return (__m128d)__builtin_ia32_cvtpi2pd ((__v2si) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_epi32 (__m128 __A) +{ + return (__m128i)__builtin_ia32_cvtps2dq ((__v4sf) __A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttps_epi32 (__m128 __A) +{ + return (__m128i)__builtin_ia32_cvttps2dq ((__v4sf) __A); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_pd (__m128 __A) +{ + return (__m128d)__builtin_ia32_cvtps2pd ((__v4sf) __A); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_si32 (__m128d __A) +{ + return __builtin_ia32_cvtsd2si ((__v2df) __A); +} + +#ifdef __x86_64__ +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_si64 (__m128d __A) +{ + return __builtin_ia32_cvtsd2si64 ((__v2df) __A); +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_si64x (__m128d __A) +{ + return __builtin_ia32_cvtsd2si64 ((__v2df) __A); +} +#endif + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_si32 (__m128d __A) +{ + return __builtin_ia32_cvttsd2si ((__v2df) __A); +} + +#ifdef __x86_64__ +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_si64 (__m128d __A) +{ + return __builtin_ia32_cvttsd2si64 ((__v2df) __A); +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttsd_si64x (__m128d __A) +{ + return __builtin_ia32_cvttsd2si64 ((__v2df) __A); +} +#endif + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsd_ss (__m128 __A, __m128d __B) +{ + return (__m128)__builtin_ia32_cvtsd2ss ((__v4sf) __A, (__v2df) __B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi32_sd (__m128d __A, int __B) +{ + return (__m128d)__builtin_ia32_cvtsi2sd ((__v2df) __A, __B); +} + +#ifdef __x86_64__ +/* Intel intrinsic. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_sd (__m128d __A, long long __B) +{ + return (__m128d)__builtin_ia32_cvtsi642sd ((__v2df) __A, __B); +} + +/* Microsoft intrinsic. */ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64x_sd (__m128d __A, long long __B) +{ + return (__m128d)__builtin_ia32_cvtsi642sd ((__v2df) __A, __B); +} +#endif + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_sd (__m128d __A, __m128 __B) +{ + return (__m128d)__builtin_ia32_cvtss2sd ((__v2df) __A, (__v4sf)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_pd(__m128d __A, __m128d __B, const int __mask) +{ + return (__m128d)__builtin_ia32_shufpd ((__v2df)__A, (__v2df)__B, __mask); +} +#else +#define _mm_shuffle_pd(A, B, N) \ + ((__m128d)__builtin_ia32_shufpd ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(N))) +#endif + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_unpckhpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pd (__m128d __A, __m128d __B) +{ + return (__m128d)__builtin_ia32_unpcklpd ((__v2df)__A, (__v2df)__B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadh_pd (__m128d __A, double const *__B) +{ + return (__m128d)__builtin_ia32_loadhpd ((__v2df)__A, __B); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadl_pd (__m128d __A, double const *__B) +{ + return (__m128d)__builtin_ia32_loadlpd ((__v2df)__A, __B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_pd (__m128d __A) +{ + return __builtin_ia32_movmskpd ((__v2df)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_packsswb128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_packssdw128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packus_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_packuswb128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpckhbw128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpckhwd128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpckhdq128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpckhqdq128 ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpcklbw128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpcklwd128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpckldq128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_punpcklqdq128 ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v16qu)__A + (__v16qu)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hu)__A + (__v8hu)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4su)__A + (__v4su)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A + (__v2du)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_paddsb128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_paddsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_paddusb128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_epu16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_paddusw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v16qu)__A - (__v16qu)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hu)__A - (__v8hu)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4su)__A - (__v4su)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A - (__v2du)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psubsb128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psubsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psubusb128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_epu16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psubusw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_madd_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmaddwd128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhi_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmulhw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mullo_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hu)__A * (__v8hu)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_su32 (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pmuludq ((__v2si)__A, (__v2si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmuludq128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_epi16 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psllwi128 ((__v8hi)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_epi32 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_epi64 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psllqi128 ((__v2di)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srai_epi16 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psrawi128 ((__v8hi)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srai_epi32 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psradi128 ((__v4si)__A, __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bsrli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bslli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8); +} +#else +#define _mm_bsrli_si128(A, N) \ + ((__m128i)__builtin_ia32_psrldqi128 ((__m128i)(A), (int)(N) * 8)) +#define _mm_bslli_si128(A, N) \ + ((__m128i)__builtin_ia32_pslldqi128 ((__m128i)(A), (int)(N) * 8)) +#define _mm_srli_si128(A, N) \ + ((__m128i)__builtin_ia32_psrldqi128 ((__m128i)(A), (int)(N) * 8)) +#define _mm_slli_si128(A, N) \ + ((__m128i)__builtin_ia32_pslldqi128 ((__m128i)(A), (int)(N) * 8)) +#endif + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_epi16 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psrlwi128 ((__v8hi)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_epi32 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psrldi128 ((__v4si)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_epi64 (__m128i __A, int __B) +{ + return (__m128i)__builtin_ia32_psrlqi128 ((__v2di)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psllw128((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pslld128((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psllq128((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sra_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psraw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sra_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psrad128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psrlw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psrld128 ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_epi64 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psrlq128 ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_and_si128 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A & (__v2du)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_andnot_si128 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pandn128 ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_si128 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A | (__v2du)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_si128 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v2du)__A ^ (__v2du)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v16qi)__A == (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hi)__A == (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4si)__A == (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v16qs)__A < (__v16qs)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hi)__A < (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4si)__A < (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v16qs)__A > (__v16qs)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v8hi)__A > (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4si)__A > (__v4si)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_epi16 (__m128i const __A, int const __N) +{ + return (unsigned short) __builtin_ia32_vec_ext_v8hi ((__v8hi)__A, __N); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_epi16 (__m128i const __A, int const __D, int const __N) +{ + return (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)__A, __D, __N); +} +#else +#define _mm_extract_epi16(A, N) \ + ((int) (unsigned short) __builtin_ia32_vec_ext_v8hi ((__v8hi)(__m128i)(A), (int)(N))) +#define _mm_insert_epi16(A, D, N) \ + ((__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)(__m128i)(A), \ + (int)(D), (int)(N))) +#endif + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmaxsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmaxub128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epi16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pminsw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pminub128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_epi8 (__m128i __A) +{ + return __builtin_ia32_pmovmskb128 ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhi_epu16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pmulhuw128 ((__v8hi)__A, (__v8hi)__B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shufflehi_epi16 (__m128i __A, const int __mask) +{ + return (__m128i)__builtin_ia32_pshufhw ((__v8hi)__A, __mask); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shufflelo_epi16 (__m128i __A, const int __mask) +{ + return (__m128i)__builtin_ia32_pshuflw ((__v8hi)__A, __mask); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_epi32 (__m128i __A, const int __mask) +{ + return (__m128i)__builtin_ia32_pshufd ((__v4si)__A, __mask); +} +#else +#define _mm_shufflehi_epi16(A, N) \ + ((__m128i)__builtin_ia32_pshufhw ((__v8hi)(__m128i)(A), (int)(N))) +#define _mm_shufflelo_epi16(A, N) \ + ((__m128i)__builtin_ia32_pshuflw ((__v8hi)(__m128i)(A), (int)(N))) +#define _mm_shuffle_epi32(A, N) \ + ((__m128i)__builtin_ia32_pshufd ((__v4si)(__m128i)(A), (int)(N))) +#endif + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskmoveu_si128 (__m128i __A, __m128i __B, char *__C) +{ + __builtin_ia32_maskmovdqu ((__v16qi)__A, (__v16qi)__B, __C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avg_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pavgb128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avg_epu16 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_pavgw128 ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sad_epu8 (__m128i __A, __m128i __B) +{ + return (__m128i)__builtin_ia32_psadbw128 ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_si32 (int *__A, int __B) +{ + __builtin_ia32_movnti (__A, __B); +} + +#ifdef __x86_64__ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_si64 (long long int *__A, long long int __B) +{ + __builtin_ia32_movnti64 (__A, __B); +} +#endif + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_si128 (__m128i *__A, __m128i __B) +{ + __builtin_ia32_movntdq ((__v2di *)__A, (__v2di)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_pd (double *__A, __m128d __B) +{ + __builtin_ia32_movntpd (__A, (__v2df)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_clflush (void const *__A) +{ + __builtin_ia32_clflush (__A); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_lfence (void) +{ + __builtin_ia32_lfence (); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mfence (void) +{ + __builtin_ia32_mfence (); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi32_si128 (int __A) +{ + return _mm_set_epi32 (0, 0, 0, __A); +} + +#ifdef __x86_64__ +/* Intel intrinsic. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_si128 (long long __A) +{ + return _mm_set_epi64x (0, __A); +} + +/* Microsoft intrinsic. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64x_si128 (long long __A) +{ + return _mm_set_epi64x (0, __A); +} +#endif + +/* Casts between various SP, DP, INT vector types. Note that these do no + conversion of values, they just change the type. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castpd_ps(__m128d __A) +{ + return (__m128) __A; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castpd_si128(__m128d __A) +{ + return (__m128i) __A; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castps_pd(__m128 __A) +{ + return (__m128d) __A; +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castps_si128(__m128 __A) +{ + return (__m128i) __A; +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castsi128_ps(__m128i __A) +{ + return (__m128) __A; +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_castsi128_pd(__m128i __A) +{ + return (__m128d) __A; +} + +#ifdef __DISABLE_SSE2__ +#undef __DISABLE_SSE2__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE2__ */ + +#endif /* _EMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/enqcmdintrin.h b/template/sysroot/include/enqcmdintrin.h new file mode 100644 index 0000000..68d68c1 --- /dev/null +++ b/template/sysroot/include/enqcmdintrin.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _ENQCMDINTRIN_H_INCLUDED +#define _ENQCMDINTRIN_H_INCLUDED + +#ifndef __ENQCMD__ +#pragma GCC push_options +#pragma GCC target ("enqcmd") +#define __DISABLE_ENQCMD__ +#endif /* __ENQCMD__ */ + +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_enqcmd (void * __P, const void * __Q) +{ + return __builtin_ia32_enqcmd (__P, __Q); +} + +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_enqcmds (void * __P, const void * __Q) +{ + return __builtin_ia32_enqcmds (__P, __Q); +} + +#ifdef __DISABLE_ENQCMD__ +#undef __DISABLE_ENQCMD__ +#pragma GCC pop_options +#endif /* __DISABLE_ENQCMD__ */ +#endif /* _ENQCMDINTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/exception b/template/sysroot/include/exception new file mode 100644 index 0000000..1b902e9 --- /dev/null +++ b/template/sysroot/include/exception @@ -0,0 +1,170 @@ +// Exception Handling support header for -*- C++ -*- + +// Copyright (C) 1995-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file exception + * This is a Standard C++ Library header. + */ + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#pragma GCC system_header + +#include +#include + +#define __glibcxx_want_uncaught_exceptions +#include + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ + /** @addtogroup exceptions + * @{ + */ + + /** If an %exception is thrown which is not listed in a function's + * %exception specification, one of these may be thrown. + * + * @ingroup exceptions + */ + class bad_exception : public exception + { + public: + bad_exception() _GLIBCXX_USE_NOEXCEPT { } + + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT; + + // See comment in eh_exception.cc. + virtual const char* + what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT; + }; + + /// If you write a replacement %terminate handler, it must be of this type. + typedef void (*terminate_handler) (); + + /// Takes a new handler function as an argument, returns the old function. + terminate_handler set_terminate(terminate_handler) _GLIBCXX_USE_NOEXCEPT; + +#if __cplusplus >= 201103L + /// Return the current terminate handler. + terminate_handler get_terminate() noexcept; +#endif + + /** The runtime will call this function if %exception handling must be + * abandoned for any reason. It can also be called by the user. */ + void terminate() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__noreturn__,__cold__)); + +#if __cplusplus < 201703L || (__cplusplus <= 202002L && _GLIBCXX_USE_DEPRECATED) + /// If you write a replacement %unexpected handler, it must be of this type. + typedef void (*_GLIBCXX11_DEPRECATED unexpected_handler) (); + + /** Takes a new handler function as an argument, returns the old function. + * + * @deprecated Removed from the C++ standard in C++17 + */ + _GLIBCXX11_DEPRECATED + unexpected_handler set_unexpected(unexpected_handler) _GLIBCXX_USE_NOEXCEPT; + +#if __cplusplus >= 201103L + /** Return the current unexpected handler. + * + * @since C++11 + * @deprecated Removed from the C++ standard in C++17 + */ + _GLIBCXX11_DEPRECATED + unexpected_handler get_unexpected() noexcept; +#endif + + /** The runtime will call this function if an %exception is thrown which + * violates the function's %exception specification. + * + * @deprecated Removed from the C++ standard in C++17 + */ + _GLIBCXX11_DEPRECATED + void unexpected() __attribute__ ((__noreturn__,__cold__)); +#endif + + /** [18.6.4]/1: 'Returns true after completing evaluation of a + * throw-expression until either completing initialization of the + * exception-declaration in the matching handler or entering `unexpected()` + * due to the throw; or after entering `terminate()` for any reason + * other than an explicit call to `terminate()`. [Note: This includes + * stack unwinding [15.2]. end note]' + * + * 2: 'When `uncaught_exception()` is true, throwing an + * %exception can result in a call of 1terminate()` + * (15.5.1).' + */ + _GLIBCXX17_DEPRECATED_SUGGEST("std::uncaught_exceptions()") + bool uncaught_exception() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__)); + +#ifdef __cpp_lib_uncaught_exceptions // C++ >= 17 || GNU++ >= 03 + /** The number of uncaught exceptions. + * @since C++17, or any non-strict mode, e.g. `-std=gnu++98` + * @see uncaught_exception() + */ + int uncaught_exceptions() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__)); +#endif + + /// @} group exceptions +} // namespace std + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A replacement for the standard terminate_handler which + * prints more information about the terminating exception (if any) + * on stderr. + * + * @ingroup exceptions + * + * Call + * @code + * std::set_terminate(__gnu_cxx::__verbose_terminate_handler) + * @endcode + * to use. For more info, see + * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt02ch06s02.html + * + * In 3.4 and later, this is on by default. + */ + void __verbose_terminate_handler(); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +} // extern "C++" + +#if (__cplusplus >= 201103L) +#include +#include +#endif + +#endif diff --git a/template/sysroot/include/expected b/template/sysroot/include/expected new file mode 100644 index 0000000..86026c3 --- /dev/null +++ b/template/sysroot/include/expected @@ -0,0 +1,1852 @@ +// -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/expected + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_EXPECTED +#define _GLIBCXX_EXPECTED + +#pragma GCC system_header + +#define __glibcxx_want_expected +#define __glibcxx_want_freestanding_expected +#include + +#ifdef __cpp_lib_expected // C++ >= 23 && __cpp_concepts >= 202002L +#include +#include // exception +#include // __invoke +#include // construct_at +#include // in_place_t + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup expected_values Expected values + * @addtogroup utilities + * @since C++23 + * @{ + */ + + /// Discriminated union that holds an expected value or an error value. + /** + * @since C++23 + */ + template + class expected; + + /// Wrapper type used to pass an error value to a `std::expected`. + /** + * @since C++23 + */ + template + class unexpected; + + /// Exception thrown by std::expected when the value() is not present. + /** + * @since C++23 + */ + template + class bad_expected_access; + + template<> + class bad_expected_access : public exception + { + protected: + bad_expected_access() noexcept { } + bad_expected_access(const bad_expected_access&) = default; + bad_expected_access(bad_expected_access&&) = default; + bad_expected_access& operator=(const bad_expected_access&) = default; + bad_expected_access& operator=(bad_expected_access&&) = default; + ~bad_expected_access() = default; + + public: + + [[nodiscard]] + const char* + what() const noexcept override + { return "bad access to std::expected without expected value"; } + }; + + template + class bad_expected_access : public bad_expected_access { + public: + explicit + bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { } + + // XXX const char* what() const noexcept override; + + [[nodiscard]] + _Er& + error() & noexcept + { return _M_unex; } + + [[nodiscard]] + const _Er& + error() const & noexcept + { return _M_unex; } + + [[nodiscard]] + _Er&& + error() && noexcept + { return std::move(_M_unex); } + + [[nodiscard]] + const _Er&& + error() const && noexcept + { return std::move(_M_unex); } + + private: + _Er _M_unex; + }; + + /// Tag type for constructing unexpected values in a std::expected + /** + * @since C++23 + */ + struct unexpect_t + { + explicit unexpect_t() = default; + }; + + /// Tag for constructing unexpected values in a std::expected + /** + * @since C++23 + */ + inline constexpr unexpect_t unexpect{}; + +/// @cond undocumented +namespace __expected +{ + template + constexpr bool __is_expected = false; + template + constexpr bool __is_expected> = true; + + template + constexpr bool __is_unexpected = false; + template + constexpr bool __is_unexpected> = true; + + template + using __result = remove_cvref_t>; + template + using __result_xform = remove_cv_t>; + template + using __result0 = remove_cvref_t>; + template + using __result0_xform = remove_cv_t>; + + template + concept __can_be_unexpected + = is_object_v<_Er> && (!is_array_v<_Er>) + && (!__expected::__is_unexpected<_Er>) + && (!is_const_v<_Er>) && (!is_volatile_v<_Er>); + + // Tag types for in-place construction from an invocation result. + struct __in_place_inv { }; + struct __unexpect_inv { }; +} +/// @endcond + + template + class unexpected + { + static_assert( __expected::__can_be_unexpected<_Er> ); + + public: + constexpr unexpected(const unexpected&) = default; + constexpr unexpected(unexpected&&) = default; + + template + requires (!is_same_v, unexpected>) + && (!is_same_v, in_place_t>) + && is_constructible_v<_Er, _Err> + constexpr explicit + unexpected(_Err&& __e) + noexcept(is_nothrow_constructible_v<_Er, _Err>) + : _M_unex(std::forward<_Err>(__e)) + { } + + template + requires is_constructible_v<_Er, _Args...> + constexpr explicit + unexpected(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, _Args...>) + : _M_unex(std::forward<_Args>(__args)...) + { } + + template + requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...> + constexpr explicit + unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&, + _Args...>) + : _M_unex(__il, std::forward<_Args>(__args)...) + { } + + constexpr unexpected& operator=(const unexpected&) = default; + constexpr unexpected& operator=(unexpected&&) = default; + + + [[nodiscard]] + constexpr const _Er& + error() const & noexcept { return _M_unex; } + + [[nodiscard]] + constexpr _Er& + error() & noexcept { return _M_unex; } + + [[nodiscard]] + constexpr const _Er&& + error() const && noexcept { return std::move(_M_unex); } + + [[nodiscard]] + constexpr _Er&& + error() && noexcept { return std::move(_M_unex); } + + constexpr void + swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>) + requires is_swappable_v<_Er> + { + using std::swap; + swap(_M_unex, __other._M_unex); + } + + template + [[nodiscard]] + friend constexpr bool + operator==(const unexpected& __x, const unexpected<_Err>& __y) + { return __x._M_unex == __y.error(); } + + friend constexpr void + swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y))) + requires is_swappable_v<_Er> + { __x.swap(__y); } + + private: + _Er _M_unex; + }; + + template unexpected(_Er) -> unexpected<_Er>; + +/// @cond undocumented +namespace __expected +{ + template + struct _Guard + { + static_assert( is_nothrow_move_constructible_v<_Tp> ); + + constexpr explicit + _Guard(_Tp& __x) + : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow + { std::destroy_at(_M_guarded); } + + constexpr + ~_Guard() + { + if (_M_guarded) [[unlikely]] + std::construct_at(_M_guarded, std::move(_M_tmp)); + } + + _Guard(const _Guard&) = delete; + _Guard& operator=(const _Guard&) = delete; + + constexpr _Tp&& + release() noexcept + { + _M_guarded = nullptr; + return std::move(_M_tmp); + } + + private: + _Tp* _M_guarded; + _Tp _M_tmp; + }; + + // reinit-expected helper from [expected.object.assign] + template + constexpr void + __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg) + noexcept(is_nothrow_constructible_v<_Tp, _Vp>) + { + if constexpr (is_nothrow_constructible_v<_Tp, _Vp>) + { + std::destroy_at(__oldval); + std::construct_at(__newval, std::forward<_Vp>(__arg)); + } + else if constexpr (is_nothrow_move_constructible_v<_Tp>) + { + _Tp __tmp(std::forward<_Vp>(__arg)); // might throw + std::destroy_at(__oldval); + std::construct_at(__newval, std::move(__tmp)); + } + else + { + _Guard<_Up> __guard(*__oldval); + std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw + __guard.release(); + } + } +} +/// @endcond + + template + class expected + { + static_assert( ! is_reference_v<_Tp> ); + static_assert( ! is_function_v<_Tp> ); + static_assert( ! is_same_v, in_place_t> ); + static_assert( ! is_same_v, unexpect_t> ); + static_assert( ! __expected::__is_unexpected> ); + static_assert( __expected::__can_be_unexpected<_Er> ); + + template> + static constexpr bool __cons_from_expected + = __or_v&>, + is_constructible<_Tp, expected<_Up, _Err>>, + is_constructible<_Tp, const expected<_Up, _Err>&>, + is_constructible<_Tp, const expected<_Up, _Err>>, + is_convertible&, _Tp>, + is_convertible, _Tp>, + is_convertible&, _Tp>, + is_convertible, _Tp>, + is_constructible<_Unex, expected<_Up, _Err>&>, + is_constructible<_Unex, expected<_Up, _Err>>, + is_constructible<_Unex, const expected<_Up, _Err>&>, + is_constructible<_Unex, const expected<_Up, _Err>> + >; + + template + constexpr static bool __explicit_conv + = __or_v<__not_>, + __not_> + >; + + template + static constexpr bool __same_val + = is_same_v; + + template + static constexpr bool __same_err + = is_same_v; + + public: + using value_type = _Tp; + using error_type = _Er; + using unexpected_type = unexpected<_Er>; + + template + using rebind = expected<_Up, error_type>; + + constexpr + expected() + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires is_default_constructible_v<_Tp> + : _M_val(), _M_has_value(true) + { } + + expected(const expected&) = default; + + constexpr + expected(const expected& __x) + noexcept(__and_v, + is_nothrow_copy_constructible<_Er>>) + requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er> + && (!is_trivially_copy_constructible_v<_Tp> + || !is_trivially_copy_constructible_v<_Er>) + : _M_has_value(__x._M_has_value) + { + if (_M_has_value) + std::construct_at(__builtin_addressof(_M_val), __x._M_val); + else + std::construct_at(__builtin_addressof(_M_unex), __x._M_unex); + } + + expected(expected&&) = default; + + constexpr + expected(expected&& __x) + noexcept(__and_v, + is_nothrow_move_constructible<_Er>>) + requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er> + && (!is_trivially_move_constructible_v<_Tp> + || !is_trivially_move_constructible_v<_Er>) + : _M_has_value(__x._M_has_value) + { + if (_M_has_value) + std::construct_at(__builtin_addressof(_M_val), + std::move(__x)._M_val); + else + std::construct_at(__builtin_addressof(_M_unex), + std::move(__x)._M_unex); + } + + template + requires is_constructible_v<_Tp, const _Up&> + && is_constructible_v<_Er, const _Gr&> + && (!__cons_from_expected<_Up, _Gr>) + constexpr explicit(__explicit_conv) + expected(const expected<_Up, _Gr>& __x) + noexcept(__and_v, + is_nothrow_constructible<_Er, const _Gr&>>) + : _M_has_value(__x._M_has_value) + { + if (_M_has_value) + std::construct_at(__builtin_addressof(_M_val), __x._M_val); + else + std::construct_at(__builtin_addressof(_M_unex), __x._M_unex); + } + + template + requires is_constructible_v<_Tp, _Up> + && is_constructible_v<_Er, _Gr> + && (!__cons_from_expected<_Up, _Gr>) + constexpr explicit(__explicit_conv<_Up, _Gr>) + expected(expected<_Up, _Gr>&& __x) + noexcept(__and_v, + is_nothrow_constructible<_Er, _Gr>>) + : _M_has_value(__x._M_has_value) + { + if (_M_has_value) + std::construct_at(__builtin_addressof(_M_val), + std::move(__x)._M_val); + else + std::construct_at(__builtin_addressof(_M_unex), + std::move(__x)._M_unex); + } + + template + requires (!is_same_v, expected>) + && (!is_same_v, in_place_t>) + && (!__expected::__is_unexpected>) + && is_constructible_v<_Tp, _Up> + constexpr explicit(!is_convertible_v<_Up, _Tp>) + expected(_Up&& __v) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : _M_val(std::forward<_Up>(__v)), _M_has_value(true) + { } + + template + requires is_constructible_v<_Er, const _Gr&> + constexpr explicit(!is_convertible_v) + expected(const unexpected<_Gr>& __u) + noexcept(is_nothrow_constructible_v<_Er, const _Gr&>) + : _M_unex(__u.error()), _M_has_value(false) + { } + + template + requires is_constructible_v<_Er, _Gr> + constexpr explicit(!is_convertible_v<_Gr, _Er>) + expected(unexpected<_Gr>&& __u) + noexcept(is_nothrow_constructible_v<_Er, _Gr>) + : _M_unex(std::move(__u).error()), _M_has_value(false) + { } + + template + requires is_constructible_v<_Tp, _Args...> + constexpr explicit + expected(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : _M_val(std::forward<_Args>(__args)...), _M_has_value(true) + { } + + template + requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> + constexpr explicit + expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, + _Args...>) + : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true) + { } + + template + requires is_constructible_v<_Er, _Args...> + constexpr explicit + expected(unexpect_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, _Args...>) + : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false) + { } + + template + requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...> + constexpr explicit + expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&, + _Args...>) + : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false) + { } + + constexpr ~expected() = default; + + constexpr ~expected() + requires (!is_trivially_destructible_v<_Tp>) + || (!is_trivially_destructible_v<_Er>) + { + if (_M_has_value) + std::destroy_at(__builtin_addressof(_M_val)); + else + std::destroy_at(__builtin_addressof(_M_unex)); + } + + // assignment + + expected& operator=(const expected&) = delete; + + constexpr expected& + operator=(const expected& __x) + noexcept(__and_v, + is_nothrow_copy_constructible<_Er>, + is_nothrow_copy_assignable<_Tp>, + is_nothrow_copy_assignable<_Er>>) + requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp> + && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er> + && (is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + { + if (__x._M_has_value) + this->_M_assign_val(__x._M_val); + else + this->_M_assign_unex(__x._M_unex); + return *this; + } + + constexpr expected& + operator=(expected&& __x) + noexcept(__and_v, + is_nothrow_move_constructible<_Er>, + is_nothrow_move_assignable<_Tp>, + is_nothrow_move_assignable<_Er>>) + requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp> + && is_move_assignable_v<_Er> && is_move_constructible_v<_Er> + && (is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + { + if (__x._M_has_value) + _M_assign_val(std::move(__x._M_val)); + else + _M_assign_unex(std::move(__x._M_unex)); + return *this; + } + + template + requires (!is_same_v>) + && (!__expected::__is_unexpected>) + && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> + && (is_nothrow_constructible_v<_Tp, _Up> + || is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + constexpr expected& + operator=(_Up&& __v) + { + _M_assign_val(std::forward<_Up>(__v)); + return *this; + } + + template + requires is_constructible_v<_Er, const _Gr&> + && is_assignable_v<_Er&, const _Gr&> + && (is_nothrow_constructible_v<_Er, const _Gr&> + || is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + constexpr expected& + operator=(const unexpected<_Gr>& __e) + { + _M_assign_unex(__e.error()); + return *this; + } + + template + requires is_constructible_v<_Er, _Gr> + && is_assignable_v<_Er&, _Gr> + && (is_nothrow_constructible_v<_Er, _Gr> + || is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + constexpr expected& + operator=(unexpected<_Gr>&& __e) + { + _M_assign_unex(std::move(__e).error()); + return *this; + } + + // modifiers + + template + requires is_nothrow_constructible_v<_Tp, _Args...> + constexpr _Tp& + emplace(_Args&&... __args) noexcept + { + if (_M_has_value) + std::destroy_at(__builtin_addressof(_M_val)); + else + { + std::destroy_at(__builtin_addressof(_M_unex)); + _M_has_value = true; + } + std::construct_at(__builtin_addressof(_M_val), + std::forward<_Args>(__args)...); + return _M_val; + } + + template + requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, + _Args...> + constexpr _Tp& + emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept + { + if (_M_has_value) + std::destroy_at(__builtin_addressof(_M_val)); + else + { + std::destroy_at(__builtin_addressof(_M_unex)); + _M_has_value = true; + } + std::construct_at(__builtin_addressof(_M_val), + __il, std::forward<_Args>(__args)...); + return _M_val; + } + + // swap + constexpr void + swap(expected& __x) + noexcept(__and_v, + is_nothrow_move_constructible<_Er>, + is_nothrow_swappable<_Tp&>, + is_nothrow_swappable<_Er&>>) + requires is_swappable_v<_Tp> && is_swappable_v<_Er> + && is_move_constructible_v<_Tp> + && is_move_constructible_v<_Er> + && (is_nothrow_move_constructible_v<_Tp> + || is_nothrow_move_constructible_v<_Er>) + { + if (_M_has_value) + { + if (__x._M_has_value) + { + using std::swap; + swap(_M_val, __x._M_val); + } + else + this->_M_swap_val_unex(__x); + } + else + { + if (__x._M_has_value) + __x._M_swap_val_unex(*this); + else + { + using std::swap; + swap(_M_unex, __x._M_unex); + } + } + } + + // observers + + [[nodiscard]] + constexpr const _Tp* + operator->() const noexcept + { + __glibcxx_assert(_M_has_value); + return __builtin_addressof(_M_val); + } + + [[nodiscard]] + constexpr _Tp* + operator->() noexcept + { + __glibcxx_assert(_M_has_value); + return __builtin_addressof(_M_val); + } + + [[nodiscard]] + constexpr const _Tp& + operator*() const & noexcept + { + __glibcxx_assert(_M_has_value); + return _M_val; + } + + [[nodiscard]] + constexpr _Tp& + operator*() & noexcept + { + __glibcxx_assert(_M_has_value); + return _M_val; + } + + [[nodiscard]] + constexpr const _Tp&& + operator*() const && noexcept + { + __glibcxx_assert(_M_has_value); + return std::move(_M_val); + } + + [[nodiscard]] + constexpr _Tp&& + operator*() && noexcept + { + __glibcxx_assert(_M_has_value); + return std::move(_M_val); + } + + [[nodiscard]] + constexpr explicit + operator bool() const noexcept { return _M_has_value; } + + [[nodiscard]] + constexpr bool has_value() const noexcept { return _M_has_value; } + + constexpr const _Tp& + value() const & + { + if (_M_has_value) [[likely]] + return _M_val; + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex)); + } + + constexpr _Tp& + value() & + { + if (_M_has_value) [[likely]] + return _M_val; + const auto& __unex = _M_unex; + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__unex)); + } + + constexpr const _Tp&& + value() const && + { + if (_M_has_value) [[likely]] + return std::move(_M_val); + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex))); + } + + constexpr _Tp&& + value() && + { + if (_M_has_value) [[likely]] + return std::move(_M_val); + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex))); + } + + constexpr const _Er& + error() const & noexcept + { + __glibcxx_assert(!_M_has_value); + return _M_unex; + } + + constexpr _Er& + error() & noexcept + { + __glibcxx_assert(!_M_has_value); + return _M_unex; + } + + constexpr const _Er&& + error() const && noexcept + { + __glibcxx_assert(!_M_has_value); + return std::move(_M_unex); + } + + constexpr _Er&& + error() && noexcept + { + __glibcxx_assert(!_M_has_value); + return std::move(_M_unex); + } + + template + constexpr _Tp + value_or(_Up&& __v) const & + noexcept(__and_v, + is_nothrow_convertible<_Up, _Tp>>) + { + static_assert( is_copy_constructible_v<_Tp> ); + static_assert( is_convertible_v<_Up, _Tp> ); + + if (_M_has_value) + return _M_val; + return static_cast<_Tp>(std::forward<_Up>(__v)); + } + + template + constexpr _Tp + value_or(_Up&& __v) && + noexcept(__and_v, + is_nothrow_convertible<_Up, _Tp>>) + { + static_assert( is_move_constructible_v<_Tp> ); + static_assert( is_convertible_v<_Up, _Tp> ); + + if (_M_has_value) + return std::move(_M_val); + return static_cast<_Tp>(std::forward<_Up>(__v)); + } + + template + constexpr _Er + error_or(_Gr&& __e) const& + { + static_assert( is_copy_constructible_v<_Er> ); + static_assert( is_convertible_v<_Gr, _Er> ); + + if (_M_has_value) + return std::forward<_Gr>(__e); + return _M_unex; + } + + template + constexpr _Er + error_or(_Gr&& __e) && + { + static_assert( is_move_constructible_v<_Er> ); + static_assert( is_convertible_v<_Gr, _Er> ); + + if (_M_has_value) + return std::forward<_Gr>(__e); + return std::move(_M_unex); + } + + // monadic operations + + template requires is_constructible_v<_Er, _Er&> + constexpr auto + and_then(_Fn&& __f) & + { + using _Up = __expected::__result<_Fn, _Tp&>; + static_assert(__expected::__is_expected<_Up>, + "the function passed to std::expected::and_then " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::and_then " + "must return a std::expected with the same error_type"); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), _M_val); + else + return _Up(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, const _Er&> + constexpr auto + and_then(_Fn&& __f) const & + { + using _Up = __expected::__result<_Fn, const _Tp&>; + static_assert(__expected::__is_expected<_Up>, + "the function passed to std::expected::and_then " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::and_then " + "must return a std::expected with the same error_type"); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), _M_val); + else + return _Up(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, _Er> + constexpr auto + and_then(_Fn&& __f) && + { + using _Up = __expected::__result<_Fn, _Tp&&>; + static_assert(__expected::__is_expected<_Up>, + "the function passed to std::expected::and_then " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::and_then " + "must return a std::expected with the same error_type"); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_val)); + else + return _Up(unexpect, std::move(_M_unex)); + } + + + template requires is_constructible_v<_Er, const _Er> + constexpr auto + and_then(_Fn&& __f) const && + { + using _Up = __expected::__result<_Fn, const _Tp&&>; + static_assert(__expected::__is_expected<_Up>, + "the function passed to std::expected::and_then " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::and_then " + "must return a std::expected with the same error_type"); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_val)); + else + return _Up(unexpect, std::move(_M_unex)); + } + + template requires is_constructible_v<_Tp, _Tp&> + constexpr auto + or_else(_Fn&& __f) & + { + using _Gr = __expected::__result<_Fn, _Er&>; + static_assert(__expected::__is_expected<_Gr>, + "the function passed to std::expected::or_else " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::or_else " + "must return a std::expected with the same value_type"); + + if (has_value()) + return _Gr(in_place, _M_val); + else + return std::__invoke(std::forward<_Fn>(__f), _M_unex); + } + + template requires is_constructible_v<_Tp, const _Tp&> + constexpr auto + or_else(_Fn&& __f) const & + { + using _Gr = __expected::__result<_Fn, const _Er&>; + static_assert(__expected::__is_expected<_Gr>, + "the function passed to std::expected::or_else " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::or_else " + "must return a std::expected with the same value_type"); + + if (has_value()) + return _Gr(in_place, _M_val); + else + return std::__invoke(std::forward<_Fn>(__f), _M_unex); + } + + + template requires is_constructible_v<_Tp, _Tp> + constexpr auto + or_else(_Fn&& __f) && + { + using _Gr = __expected::__result<_Fn, _Er&&>; + static_assert(__expected::__is_expected<_Gr>, + "the function passed to std::expected::or_else " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::or_else " + "must return a std::expected with the same value_type"); + + if (has_value()) + return _Gr(in_place, std::move(_M_val)); + else + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex)); + } + + template requires is_constructible_v<_Tp, const _Tp> + constexpr auto + or_else(_Fn&& __f) const && + { + using _Gr = __expected::__result<_Fn, const _Er&&>; + static_assert(__expected::__is_expected<_Gr>, + "the function passed to std::expected::or_else " + "must return a std::expected"); + static_assert(is_same_v, + "the function passed to std::expected::or_else " + "must return a std::expected with the same value_type"); + + if (has_value()) + return _Gr(in_place, std::move(_M_val)); + else + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex)); + } + + template requires is_constructible_v<_Er, _Er&> + constexpr auto + transform(_Fn&& __f) & + { + using _Up = __expected::__result_xform<_Fn, _Tp&>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_val); + }); + else + return _Res(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, const _Er&> + constexpr auto + transform(_Fn&& __f) const & + { + using _Up = __expected::__result_xform<_Fn, const _Tp&>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_val); + }); + else + return _Res(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, _Er> + constexpr auto + transform(_Fn&& __f) && + { + using _Up = __expected::__result_xform<_Fn, _Tp>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_val)); + }); + else + return _Res(unexpect, std::move(_M_unex)); + } + + template requires is_constructible_v<_Er, const _Er> + constexpr auto + transform(_Fn&& __f) const && + { + using _Up = __expected::__result_xform<_Fn, const _Tp>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_val)); + }); + else + return _Res(unexpect, std::move(_M_unex)); + } + + template requires is_constructible_v<_Tp, _Tp&> + constexpr auto + transform_error(_Fn&& __f) & + { + using _Gr = __expected::__result_xform<_Fn, _Er&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(in_place, _M_val); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_unex); + }); + } + + template requires is_constructible_v<_Tp, const _Tp&> + constexpr auto + transform_error(_Fn&& __f) const & + { + using _Gr = __expected::__result_xform<_Fn, const _Er&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(in_place, _M_val); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_unex); + }); + } + + template requires is_constructible_v<_Tp, _Tp> + constexpr auto + transform_error(_Fn&& __f) && + { + using _Gr = __expected::__result_xform<_Fn, _Er&&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(in_place, std::move(_M_val)); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_unex)); + }); + } + + template requires is_constructible_v<_Tp, const _Tp> + constexpr auto + transform_error(_Fn&& __f) const && + { + using _Gr = __expected::__result_xform<_Fn, const _Er&&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(in_place, std::move(_M_val)); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_unex)); + }); + } + + // equality operators + + template + requires (!is_void_v<_Up>) + friend constexpr bool + operator==(const expected& __x, const expected<_Up, _Er2>& __y) + // FIXME: noexcept(noexcept(bool(*__x == *__y)) + // && noexcept(bool(__x.error() == __y.error()))) + { + if (__x.has_value()) + return __y.has_value() && bool(*__x == *__y); + else + return !__y.has_value() && bool(__x.error() == __y.error()); + } + + template + friend constexpr bool + operator==(const expected& __x, const _Up& __v) + // FIXME: noexcept(noexcept(bool(*__x == __v))) + { return __x.has_value() && bool(*__x == __v); } + + template + friend constexpr bool + operator==(const expected& __x, const unexpected<_Er2>& __e) + // FIXME: noexcept(noexcept(bool(__x.error() == __e.error()))) + { return !__x.has_value() && bool(__x.error() == __e.error()); } + + friend constexpr void + swap(expected& __x, expected& __y) + noexcept(noexcept(__x.swap(__y))) + requires requires {__x.swap(__y);} + { __x.swap(__y); } + + private: + template friend class expected; + + template + constexpr void + _M_assign_val(_Vp&& __v) + { + if (_M_has_value) + _M_val = std::forward<_Vp>(__v); + else + { + __expected::__reinit(__builtin_addressof(_M_val), + __builtin_addressof(_M_unex), + std::forward<_Vp>(__v)); + _M_has_value = true; + } + } + + template + constexpr void + _M_assign_unex(_Vp&& __v) + { + if (_M_has_value) + { + __expected::__reinit(__builtin_addressof(_M_unex), + __builtin_addressof(_M_val), + std::forward<_Vp>(__v)); + _M_has_value = false; + } + else + _M_unex = std::forward<_Vp>(__v); + } + + // Swap two expected objects when only one has a value. + // Precondition: this->_M_has_value && !__rhs._M_has_value + constexpr void + _M_swap_val_unex(expected& __rhs) + noexcept(__and_v, + is_nothrow_move_constructible<_Tp>>) + { + if constexpr (is_nothrow_move_constructible_v<_Er>) + { + __expected::_Guard<_Er> __guard(__rhs._M_unex); + std::construct_at(__builtin_addressof(__rhs._M_val), + std::move(_M_val)); // might throw + __rhs._M_has_value = true; + std::destroy_at(__builtin_addressof(_M_val)); + std::construct_at(__builtin_addressof(_M_unex), + __guard.release()); + _M_has_value = false; + } + else + { + __expected::_Guard<_Tp> __guard(_M_val); + std::construct_at(__builtin_addressof(_M_unex), + std::move(__rhs._M_unex)); // might throw + _M_has_value = false; + std::destroy_at(__builtin_addressof(__rhs._M_unex)); + std::construct_at(__builtin_addressof(__rhs._M_val), + __guard.release()); + __rhs._M_has_value = true; + } + } + + using __in_place_inv = __expected::__in_place_inv; + using __unexpect_inv = __expected::__unexpect_inv; + + template + explicit constexpr + expected(__in_place_inv, _Fn&& __fn) + : _M_val(std::forward<_Fn>(__fn)()), _M_has_value(true) + { } + + template + explicit constexpr + expected(__unexpect_inv, _Fn&& __fn) + : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false) + { } + + union { + _Tp _M_val; + _Er _M_unex; + }; + + bool _M_has_value; + }; + + // Partial specialization for std::expected + template requires is_void_v<_Tp> + class expected<_Tp, _Er> + { + static_assert( __expected::__can_be_unexpected<_Er> ); + + template> + static constexpr bool __cons_from_expected + = __or_v&>, + is_constructible<_Unex, expected<_Up, _Err>>, + is_constructible<_Unex, const expected<_Up, _Err>&>, + is_constructible<_Unex, const expected<_Up, _Err>> + >; + + template + static constexpr bool __same_val + = is_same_v; + + template + static constexpr bool __same_err + = is_same_v; + + public: + using value_type = _Tp; + using error_type = _Er; + using unexpected_type = unexpected<_Er>; + + template + using rebind = expected<_Up, error_type>; + + constexpr + expected() noexcept + : _M_void(), _M_has_value(true) + { } + + expected(const expected&) = default; + + constexpr + expected(const expected& __x) + noexcept(is_nothrow_copy_constructible_v<_Er>) + requires is_copy_constructible_v<_Er> + && (!is_trivially_copy_constructible_v<_Er>) + : _M_void(), _M_has_value(__x._M_has_value) + { + if (!_M_has_value) + std::construct_at(__builtin_addressof(_M_unex), __x._M_unex); + } + + expected(expected&&) = default; + + constexpr + expected(expected&& __x) + noexcept(is_nothrow_move_constructible_v<_Er>) + requires is_move_constructible_v<_Er> + && (!is_trivially_move_constructible_v<_Er>) + : _M_void(), _M_has_value(__x._M_has_value) + { + if (!_M_has_value) + std::construct_at(__builtin_addressof(_M_unex), + std::move(__x)._M_unex); + } + + template + requires is_void_v<_Up> + && is_constructible_v<_Er, const _Gr&> + && (!__cons_from_expected<_Up, _Gr>) + constexpr explicit(!is_convertible_v) + expected(const expected<_Up, _Gr>& __x) + noexcept(is_nothrow_constructible_v<_Er, const _Gr&>) + : _M_void(), _M_has_value(__x._M_has_value) + { + if (!_M_has_value) + std::construct_at(__builtin_addressof(_M_unex), __x._M_unex); + } + + template + requires is_void_v<_Up> + && is_constructible_v<_Er, _Gr> + && (!__cons_from_expected<_Up, _Gr>) + constexpr explicit(!is_convertible_v<_Gr, _Er>) + expected(expected<_Up, _Gr>&& __x) + noexcept(is_nothrow_constructible_v<_Er, _Gr>) + : _M_void(), _M_has_value(__x._M_has_value) + { + if (!_M_has_value) + std::construct_at(__builtin_addressof(_M_unex), + std::move(__x)._M_unex); + } + + template + requires is_constructible_v<_Er, const _Gr&> + constexpr explicit(!is_convertible_v) + expected(const unexpected<_Gr>& __u) + noexcept(is_nothrow_constructible_v<_Er, const _Gr&>) + : _M_unex(__u.error()), _M_has_value(false) + { } + + template + requires is_constructible_v<_Er, _Gr> + constexpr explicit(!is_convertible_v<_Gr, _Er>) + expected(unexpected<_Gr>&& __u) + noexcept(is_nothrow_constructible_v<_Er, _Gr>) + : _M_unex(std::move(__u).error()), _M_has_value(false) + { } + + constexpr explicit + expected(in_place_t) noexcept + : expected() + { } + + template + requires is_constructible_v<_Er, _Args...> + constexpr explicit + expected(unexpect_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, _Args...>) + : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false) + { } + + template + requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...> + constexpr explicit + expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&, + _Args...>) + : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false) + { } + + constexpr ~expected() = default; + + constexpr ~expected() requires (!is_trivially_destructible_v<_Er>) + { + if (!_M_has_value) + std::destroy_at(__builtin_addressof(_M_unex)); + } + + // assignment + + expected& operator=(const expected&) = delete; + + constexpr expected& + operator=(const expected& __x) + noexcept(__and_v, + is_nothrow_copy_assignable<_Er>>) + requires is_copy_constructible_v<_Er> + && is_copy_assignable_v<_Er> + { + if (__x._M_has_value) + emplace(); + else + _M_assign_unex(__x._M_unex); + return *this; + } + + constexpr expected& + operator=(expected&& __x) + noexcept(__and_v, + is_nothrow_move_assignable<_Er>>) + requires is_move_constructible_v<_Er> + && is_move_assignable_v<_Er> + { + if (__x._M_has_value) + emplace(); + else + _M_assign_unex(std::move(__x._M_unex)); + return *this; + } + + template + requires is_constructible_v<_Er, const _Gr&> + && is_assignable_v<_Er&, const _Gr&> + constexpr expected& + operator=(const unexpected<_Gr>& __e) + { + _M_assign_unex(__e.error()); + return *this; + } + + template + requires is_constructible_v<_Er, _Gr> + && is_assignable_v<_Er&, _Gr> + constexpr expected& + operator=(unexpected<_Gr>&& __e) + { + _M_assign_unex(std::move(__e.error())); + return *this; + } + + // modifiers + + constexpr void + emplace() noexcept + { + if (!_M_has_value) + { + std::destroy_at(__builtin_addressof(_M_unex)); + _M_has_value = true; + } + } + + // swap + constexpr void + swap(expected& __x) + noexcept(__and_v, + is_nothrow_move_constructible<_Er>>) + requires is_swappable_v<_Er> && is_move_constructible_v<_Er> + { + if (_M_has_value) + { + if (!__x._M_has_value) + { + std::construct_at(__builtin_addressof(_M_unex), + std::move(__x._M_unex)); // might throw + std::destroy_at(__builtin_addressof(__x._M_unex)); + _M_has_value = false; + __x._M_has_value = true; + } + } + else + { + if (__x._M_has_value) + { + std::construct_at(__builtin_addressof(__x._M_unex), + std::move(_M_unex)); // might throw + std::destroy_at(__builtin_addressof(_M_unex)); + _M_has_value = true; + __x._M_has_value = false; + } + else + { + using std::swap; + swap(_M_unex, __x._M_unex); + } + } + } + + // observers + + [[nodiscard]] + constexpr explicit + operator bool() const noexcept { return _M_has_value; } + + [[nodiscard]] + constexpr bool has_value() const noexcept { return _M_has_value; } + + constexpr void + operator*() const noexcept { __glibcxx_assert(_M_has_value); } + + constexpr void + value() const& + { + if (_M_has_value) [[likely]] + return; + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex)); + } + + constexpr void + value() && + { + if (_M_has_value) [[likely]] + return; + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex))); + } + + constexpr const _Er& + error() const & noexcept + { + __glibcxx_assert(!_M_has_value); + return _M_unex; + } + + constexpr _Er& + error() & noexcept + { + __glibcxx_assert(!_M_has_value); + return _M_unex; + } + + constexpr const _Er&& + error() const && noexcept + { + __glibcxx_assert(!_M_has_value); + return std::move(_M_unex); + } + + constexpr _Er&& + error() && noexcept + { + __glibcxx_assert(!_M_has_value); + return std::move(_M_unex); + } + + template + constexpr _Er + error_or(_Gr&& __e) const& + { + static_assert( is_copy_constructible_v<_Er> ); + static_assert( is_convertible_v<_Gr, _Er> ); + + if (_M_has_value) + return std::forward<_Gr>(__e); + return _M_unex; + } + + template + constexpr _Er + error_or(_Gr&& __e) && + { + static_assert( is_move_constructible_v<_Er> ); + static_assert( is_convertible_v<_Gr, _Er> ); + + if (_M_has_value) + return std::forward<_Gr>(__e); + return std::move(_M_unex); + } + + // monadic operations + + template requires is_constructible_v<_Er, _Er&> + constexpr auto + and_then(_Fn&& __f) & + { + using _Up = __expected::__result0<_Fn>; + static_assert(__expected::__is_expected<_Up>); + static_assert(is_same_v); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f)); + else + return _Up(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, const _Er&> + constexpr auto + and_then(_Fn&& __f) const & + { + using _Up = __expected::__result0<_Fn>; + static_assert(__expected::__is_expected<_Up>); + static_assert(is_same_v); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f)); + else + return _Up(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, _Er> + constexpr auto + and_then(_Fn&& __f) && + { + using _Up = __expected::__result0<_Fn>; + static_assert(__expected::__is_expected<_Up>); + static_assert(is_same_v); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f)); + else + return _Up(unexpect, std::move(_M_unex)); + } + + template requires is_constructible_v<_Er, const _Er> + constexpr auto + and_then(_Fn&& __f) const && + { + using _Up = __expected::__result0<_Fn>; + static_assert(__expected::__is_expected<_Up>); + static_assert(is_same_v); + + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f)); + else + return _Up(unexpect, std::move(_M_unex)); + } + + template + constexpr auto + or_else(_Fn&& __f) & + { + using _Gr = __expected::__result<_Fn, _Er&>; + static_assert(__expected::__is_expected<_Gr>); + static_assert(is_same_v); + + if (has_value()) + return _Gr(); + else + return std::__invoke(std::forward<_Fn>(__f), _M_unex); + } + + template + constexpr auto + or_else(_Fn&& __f) const & + { + using _Gr = __expected::__result<_Fn, const _Er&>; + static_assert(__expected::__is_expected<_Gr>); + static_assert(is_same_v); + + if (has_value()) + return _Gr(); + else + return std::__invoke(std::forward<_Fn>(__f), _M_unex); + } + + template + constexpr auto + or_else(_Fn&& __f) && + { + using _Gr = __expected::__result<_Fn, _Er&&>; + static_assert(__expected::__is_expected<_Gr>); + static_assert(is_same_v); + + if (has_value()) + return _Gr(); + else + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex)); + } + + template + constexpr auto + or_else(_Fn&& __f) const && + { + using _Gr = __expected::__result<_Fn, const _Er&&>; + static_assert(__expected::__is_expected<_Gr>); + static_assert(is_same_v); + + if (has_value()) + return _Gr(); + else + return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex)); + } + + template requires is_constructible_v<_Er, _Er&> + constexpr auto + transform(_Fn&& __f) & + { + using _Up = __expected::__result0_xform<_Fn>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, std::forward<_Fn>(__f)); + else + return _Res(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, const _Er&> + constexpr auto + transform(_Fn&& __f) const & + { + using _Up = __expected::__result0_xform<_Fn>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, std::forward<_Fn>(__f)); + else + return _Res(unexpect, _M_unex); + } + + template requires is_constructible_v<_Er, _Er> + constexpr auto + transform(_Fn&& __f) && + { + using _Up = __expected::__result0_xform<_Fn>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, std::forward<_Fn>(__f)); + else + return _Res(unexpect, std::move(_M_unex)); + } + + template requires is_constructible_v<_Er, const _Er> + constexpr auto + transform(_Fn&& __f) const && + { + using _Up = __expected::__result0_xform<_Fn>; + using _Res = expected<_Up, _Er>; + + if (has_value()) + return _Res(__in_place_inv{}, std::forward<_Fn>(__f)); + else + return _Res(unexpect, std::move(_M_unex)); + } + + template + constexpr auto + transform_error(_Fn&& __f) & + { + using _Gr = __expected::__result_xform<_Fn, _Er&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_unex); + }); + } + + template + constexpr auto + transform_error(_Fn&& __f) const & + { + using _Gr = __expected::__result_xform<_Fn, const _Er&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + _M_unex); + }); + } + + template + constexpr auto + transform_error(_Fn&& __f) && + { + using _Gr = __expected::__result_xform<_Fn, _Er&&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_unex)); + }); + } + + template + constexpr auto + transform_error(_Fn&& __f) const && + { + using _Gr = __expected::__result_xform<_Fn, const _Er&&>; + using _Res = expected<_Tp, _Gr>; + + if (has_value()) + return _Res(); + else + return _Res(__unexpect_inv{}, [&]() { + return std::__invoke(std::forward<_Fn>(__f), + std::move(_M_unex)); + }); + } + + // equality operators + + template + requires is_void_v<_Up> + friend constexpr bool + operator==(const expected& __x, const expected<_Up, _Er2>& __y) + // FIXME: noexcept(noexcept(bool(__x.error() == __y.error()))) + { + if (__x.has_value()) + return __y.has_value(); + else + return !__y.has_value() && bool(__x.error() == __y.error()); + } + + template + friend constexpr bool + operator==(const expected& __x, const unexpected<_Er2>& __e) + // FIXME: noexcept(noexcept(bool(__x.error() == __e.error()))) + { return !__x.has_value() && bool(__x.error() == __e.error()); } + + friend constexpr void + swap(expected& __x, expected& __y) + noexcept(noexcept(__x.swap(__y))) + requires requires { __x.swap(__y); } + { __x.swap(__y); } + + private: + template friend class expected; + + template + constexpr void + _M_assign_unex(_Vp&& __v) + { + if (_M_has_value) + { + std::construct_at(__builtin_addressof(_M_unex), + std::forward<_Vp>(__v)); + _M_has_value = false; + } + else + _M_unex = std::forward<_Vp>(__v); + } + + using __in_place_inv = __expected::__in_place_inv; + using __unexpect_inv = __expected::__unexpect_inv; + + template + explicit constexpr + expected(__in_place_inv, _Fn&& __fn) + : _M_void(), _M_has_value(true) + { std::forward<_Fn>(__fn)(); } + + template + explicit constexpr + expected(__unexpect_inv, _Fn&& __fn) + : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false) + { } + + union { + struct { } _M_void; + _Er _M_unex; + }; + + bool _M_has_value; + }; + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_expected +#endif // _GLIBCXX_EXPECTED diff --git a/template/sysroot/include/ext/aligned_buffer.h b/template/sysroot/include/ext/aligned_buffer.h new file mode 100644 index 0000000..26b3660 --- /dev/null +++ b/template/sysroot/include/ext/aligned_buffer.h @@ -0,0 +1,128 @@ +// Aligned memory buffer -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/aligned_buffer.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _ALIGNED_BUFFER_H +#define _ALIGNED_BUFFER_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +# include +#else +# include +#endif + +namespace __gnu_cxx +{ + // A utility type containing a POD object that can hold an object of type + // _Tp initialized via placement new or allocator_traits::construct. + // Intended for use as a data member subobject, use __aligned_buffer for + // complete objects. + template + struct __aligned_membuf + { + // Target macro ADJUST_FIELD_ALIGN can produce different alignment for + // types when used as class members. __aligned_membuf is intended + // for use as a class member, so align the buffer as for a class member. + // Since GCC 8 we could just use alignof(_Tp) instead, but older + // versions of non-GNU compilers might still need this trick. + struct _Tp2 { _Tp _M_t; }; + + alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)]; + + __aligned_membuf() = default; + + // Can be used to avoid value-initialization zeroing _M_storage. + __aligned_membuf(std::nullptr_t) { } + + void* + _M_addr() noexcept + { return static_cast(&_M_storage); } + + const void* + _M_addr() const noexcept + { return static_cast(&_M_storage); } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; + +#if _GLIBCXX_INLINE_VERSION + template + using __aligned_buffer = __aligned_membuf<_Tp>; +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + // Similar to __aligned_membuf but aligned for complete objects, not members. + // This type is used in , , + // and , but ideally they would use __aligned_membuf + // instead, as it has smaller size for some types on some targets. + // This type is still used to avoid an ABI change. + template + struct __aligned_buffer + : std::aligned_storage + { + typename + std::aligned_storage::type _M_storage; + + __aligned_buffer() = default; + + // Can be used to avoid value-initialization + __aligned_buffer(std::nullptr_t) { } + + void* + _M_addr() noexcept + { + return static_cast(&_M_storage); + } + + const void* + _M_addr() const noexcept + { + return static_cast(&_M_storage); + } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; +#pragma GCC diagnostic pop +#endif + +} // namespace + +#endif /* _ALIGNED_BUFFER_H */ diff --git a/template/sysroot/include/ext/alloc_traits.h b/template/sysroot/include/ext/alloc_traits.h new file mode 100644 index 0000000..f778c4d --- /dev/null +++ b/template/sysroot/include/ext/alloc_traits.h @@ -0,0 +1,185 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/alloc_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_ALLOC_TRAITS_H +#define _EXT_ALLOC_TRAITS_H 1 + +#pragma GCC system_header + +# include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Uniform interface to C++98 and C++11 allocators. + * @ingroup allocators +*/ +template + struct __alloc_traits +#if __cplusplus >= 201103L + : std::allocator_traits<_Alloc> +#endif + { + typedef _Alloc allocator_type; +#if __cplusplus >= 201103L + typedef std::allocator_traits<_Alloc> _Base_type; + typedef typename _Base_type::value_type value_type; + typedef typename _Base_type::pointer pointer; + typedef typename _Base_type::const_pointer const_pointer; + typedef typename _Base_type::size_type size_type; + typedef typename _Base_type::difference_type difference_type; + // C++11 allocators do not define reference or const_reference + typedef value_type& reference; + typedef const value_type& const_reference; + using _Base_type::allocate; + using _Base_type::deallocate; + using _Base_type::construct; + using _Base_type::destroy; + using _Base_type::max_size; + + private: + template + using __is_custom_pointer + = std::__and_, + std::__not_>>; + + public: + // overload construct for non-standard pointer types + template + [[__gnu__::__always_inline__]] + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + construct(_Alloc& __a, _Ptr __p, _Args&&... __args) + noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...))) + { + _Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...); + } + + // overload destroy for non-standard pointer types + template + [[__gnu__::__always_inline__]] + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + destroy(_Alloc& __a, _Ptr __p) + noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p)))) + { _Base_type::destroy(__a, std::__to_address(__p)); } + + [[__gnu__::__always_inline__]] + static constexpr _Alloc _S_select_on_copy(const _Alloc& __a) + { return _Base_type::select_on_container_copy_construction(__a); } + + [[__gnu__::__always_inline__]] + static _GLIBCXX14_CONSTEXPR void _S_on_swap(_Alloc& __a, _Alloc& __b) + { std::__alloc_on_swap(__a, __b); } + + [[__gnu__::__always_inline__]] + static constexpr bool _S_propagate_on_copy_assign() + { return _Base_type::propagate_on_container_copy_assignment::value; } + + [[__gnu__::__always_inline__]] + static constexpr bool _S_propagate_on_move_assign() + { return _Base_type::propagate_on_container_move_assignment::value; } + + [[__gnu__::__always_inline__]] + static constexpr bool _S_propagate_on_swap() + { return _Base_type::propagate_on_container_swap::value; } + + [[__gnu__::__always_inline__]] + static constexpr bool _S_always_equal() + { return _Base_type::is_always_equal::value; } + + __attribute__((__always_inline__)) + static constexpr bool _S_nothrow_move() + { return _S_propagate_on_move_assign() || _S_always_equal(); } + + template + struct rebind + { typedef typename _Base_type::template rebind_alloc<_Tp> other; }; +#else // ! C++11 + + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::value_type value_type; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + typedef typename _Alloc::size_type size_type; + typedef typename _Alloc::difference_type difference_type; + + __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + static pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + template + __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + static pointer + allocate(_Alloc& __a, size_type __n, _Hint __hint) + { return __a.allocate(__n, __hint); } + + __attribute__((__always_inline__)) + static void deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + template + __attribute__((__always_inline__)) + static void construct(_Alloc& __a, pointer __p, const _Tp& __arg) + { __a.construct(__p, __arg); } + + __attribute__((__always_inline__)) + static void destroy(_Alloc& __a, pointer __p) + { __a.destroy(__p); } + + __attribute__((__always_inline__)) + static size_type max_size(const _Alloc& __a) + { return __a.max_size(); } + + __attribute__((__always_inline__)) + static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; } + + __attribute__((__always_inline__)) + static void _S_on_swap(_Alloc& __a, _Alloc& __b) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 431. Swapping containers with unequal allocators. + std::__alloc_swap<_Alloc>::_S_do_it(__a, __b); + } + + template + struct rebind + { typedef typename _Alloc::template rebind<_Tp>::other other; }; +#endif // C++11 + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +#endif diff --git a/template/sysroot/include/ext/atomicity.h b/template/sysroot/include/ext/atomicity.h new file mode 100644 index 0000000..cc2fe3b --- /dev/null +++ b/template/sysroot/include/ext/atomicity.h @@ -0,0 +1,127 @@ +// Support for atomic operations -*- C++ -*- + +// Copyright (C) 2004-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/atomicity.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_ATOMICITY_H +#define _GLIBCXX_ATOMICITY_H 1 + +#pragma GCC system_header + +#include +#include +#include +#if __has_include() +# include +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + __attribute__((__always_inline__)) + inline bool + __is_single_threaded() _GLIBCXX_NOTHROW + { +#ifndef __GTHREADS + return true; +#elif __has_include() + return ::__libc_single_threaded; +#else + return !__gthread_active_p(); +#endif + } + + // Functions for portable atomic access. + // To abstract locking primitives across all thread policies, use: + // __exchange_and_add_dispatch + // __atomic_add_dispatch +#ifdef _GLIBCXX_ATOMIC_BUILTINS + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add(volatile _Atomic_word* __mem, int __val) + { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } + + inline void + __attribute__((__always_inline__)) + __atomic_add(volatile _Atomic_word* __mem, int __val) + { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } +#else + _Atomic_word + __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; + + void + __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; +#endif + + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add_single(_Atomic_word* __mem, int __val) + { + _Atomic_word __result = *__mem; + *__mem += __val; + return __result; + } + + inline void + __attribute__((__always_inline__)) + __atomic_add_single(_Atomic_word* __mem, int __val) + { *__mem += __val; } + + inline _Atomic_word + __attribute__ ((__always_inline__)) + __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) + { + if (__is_single_threaded()) + return __exchange_and_add_single(__mem, __val); + else + return __exchange_and_add(__mem, __val); + } + + inline void + __attribute__ ((__always_inline__)) + __atomic_add_dispatch(_Atomic_word* __mem, int __val) + { + if (__is_single_threaded()) + __atomic_add_single(__mem, __val); + else + __atomic_add(__mem, __val); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +// Even if the CPU doesn't need a memory barrier, we need to ensure +// that the compiler doesn't reorder memory accesses across the +// barriers. +#ifndef _GLIBCXX_READ_MEM_BARRIER +#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) +#endif +#ifndef _GLIBCXX_WRITE_MEM_BARRIER +#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) +#endif + +#endif diff --git a/template/sysroot/include/ext/cast.h b/template/sysroot/include/ext/cast.h new file mode 100644 index 0000000..36a53a8 --- /dev/null +++ b/template/sysroot/include/ext/cast.h @@ -0,0 +1,121 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/cast.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/pointer.h} + */ + +#ifndef _GLIBCXX_CAST_H +#define _GLIBCXX_CAST_H 1 + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * These functions are here to allow containers to support non standard + * pointer types. For normal pointers, these resolve to the use of the + * standard cast operation. For other types the functions will perform + * the appropriate cast to/from the custom pointer class so long as that + * class meets the following conditions: + * 1) has a typedef element_type which names tehe type it points to. + * 2) has a get() const method which returns element_type*. + * 3) has a constructor which can take one element_type* argument. + */ + + /** + * This type supports the semantics of the pointer cast operators (below.) + */ + template + struct _Caster + { typedef typename _ToType::element_type* type; }; + + template + struct _Caster<_ToType*> + { typedef _ToType* type; }; + + /** + * Casting operations for cases where _FromType is not a standard pointer. + * _ToType can be a standard or non-standard pointer. Given that _FromType + * is not a pointer, it must have a get() method that returns the standard + * pointer equivalent of the address it points to, and must have an + * element_type typedef which names the type it points to. + */ + template + inline _ToType + __static_pointer_cast(const _FromType& __arg) + { return _ToType(static_cast:: + type>(__arg.get())); } + + template + inline _ToType + __dynamic_pointer_cast(const _FromType& __arg) + { return _ToType(dynamic_cast:: + type>(__arg.get())); } + + template + inline _ToType + __const_pointer_cast(const _FromType& __arg) + { return _ToType(const_cast:: + type>(__arg.get())); } + + template + inline _ToType + __reinterpret_pointer_cast(const _FromType& __arg) + { return _ToType(reinterpret_cast:: + type>(__arg.get())); } + + /** + * Casting operations for cases where _FromType is a standard pointer. + * _ToType can be a standard or non-standard pointer. + */ + template + inline _ToType + __static_pointer_cast(_FromType* __arg) + { return _ToType(static_cast:: + type>(__arg)); } + + template + inline _ToType + __dynamic_pointer_cast(_FromType* __arg) + { return _ToType(dynamic_cast:: + type>(__arg)); } + + template + inline _ToType + __const_pointer_cast(_FromType* __arg) + { return _ToType(const_cast:: + type>(__arg)); } + + template + inline _ToType + __reinterpret_pointer_cast(_FromType* __arg) + { return _ToType(reinterpret_cast:: + type>(__arg)); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // _GLIBCXX_CAST_H diff --git a/template/sysroot/include/ext/concurrence.h b/template/sysroot/include/ext/concurrence.h new file mode 100644 index 0000000..7629c1b --- /dev/null +++ b/template/sysroot/include/ext/concurrence.h @@ -0,0 +1,315 @@ +// Support for concurrent programing -*- C++ -*- + +// Copyright (C) 2003-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/concurrence.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _CONCURRENCE_H +#define _CONCURRENCE_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Available locking policies: + // _S_single single-threaded code that doesn't need to be locked. + // _S_mutex multi-threaded code that requires additional support + // from gthr.h or abstraction layers in concurrence.h. + // _S_atomic multi-threaded code using atomic operations. + enum _Lock_policy { _S_single, _S_mutex, _S_atomic }; + + // Compile time constant that indicates prefered locking policy in + // the current configuration. + _GLIBCXX17_INLINE const _Lock_policy __default_lock_policy = +#ifndef __GTHREADS + _S_single; +#elif defined _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY + _S_atomic; +#else + _S_mutex; +#endif + + // NB: As this is used in libsupc++, need to only depend on + // exception. No stdexception classes, no use of std::string. + class __concurrence_lock_error : public std::exception + { + public: + virtual char const* + what() const throw() + { return "__gnu_cxx::__concurrence_lock_error"; } + }; + + class __concurrence_unlock_error : public std::exception + { + public: + virtual char const* + what() const throw() + { return "__gnu_cxx::__concurrence_unlock_error"; } + }; + + class __concurrence_broadcast_error : public std::exception + { + public: + virtual char const* + what() const throw() + { return "__gnu_cxx::__concurrence_broadcast_error"; } + }; + + class __concurrence_wait_error : public std::exception + { + public: + virtual char const* + what() const throw() + { return "__gnu_cxx::__concurrence_wait_error"; } + }; + + // Substitute for concurrence_error object in the case of -fno-exceptions. + inline void + __throw_concurrence_lock_error() + { _GLIBCXX_THROW_OR_ABORT(__concurrence_lock_error()); } + + inline void + __throw_concurrence_unlock_error() + { _GLIBCXX_THROW_OR_ABORT(__concurrence_unlock_error()); } + +#ifdef __GTHREAD_HAS_COND + inline void + __throw_concurrence_broadcast_error() + { _GLIBCXX_THROW_OR_ABORT(__concurrence_broadcast_error()); } + + inline void + __throw_concurrence_wait_error() + { _GLIBCXX_THROW_OR_ABORT(__concurrence_wait_error()); } +#endif + + class __mutex + { + private: +#if __GTHREADS && defined __GTHREAD_MUTEX_INIT + __gthread_mutex_t _M_mutex = __GTHREAD_MUTEX_INIT; +#else + __gthread_mutex_t _M_mutex; +#endif + + __mutex(const __mutex&); + __mutex& operator=(const __mutex&); + + public: + __mutex() + { +#if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT + if (__gthread_active_p()) + __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); +#endif + } + +#if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT + ~__mutex() + { + if (__gthread_active_p()) + __gthread_mutex_destroy(&_M_mutex); + } +#endif + + void lock() + { +#if __GTHREADS + if (__gthread_active_p()) + { + if (__gthread_mutex_lock(&_M_mutex) != 0) + __throw_concurrence_lock_error(); + } +#endif + } + + void unlock() + { +#if __GTHREADS + if (__gthread_active_p()) + { + if (__gthread_mutex_unlock(&_M_mutex) != 0) + __throw_concurrence_unlock_error(); + } +#endif + } + + __gthread_mutex_t* gthread_mutex(void) + { return &_M_mutex; } + }; + + class __recursive_mutex + { + private: +#if __GTHREADS && defined __GTHREAD_RECURSIVE_MUTEX_INIT + __gthread_recursive_mutex_t _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; +#else + __gthread_recursive_mutex_t _M_mutex; +#endif + + __recursive_mutex(const __recursive_mutex&); + __recursive_mutex& operator=(const __recursive_mutex&); + + public: + __recursive_mutex() + { +#if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT + if (__gthread_active_p()) + __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); +#endif + } + +#if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT + ~__recursive_mutex() + { + if (__gthread_active_p()) + __gthread_recursive_mutex_destroy(&_M_mutex); + } +#endif + + void lock() + { +#if __GTHREADS + if (__gthread_active_p()) + { + if (__gthread_recursive_mutex_lock(&_M_mutex) != 0) + __throw_concurrence_lock_error(); + } +#endif + } + + void unlock() + { +#if __GTHREADS + if (__gthread_active_p()) + { + if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0) + __throw_concurrence_unlock_error(); + } +#endif + } + + __gthread_recursive_mutex_t* gthread_recursive_mutex(void) + { return &_M_mutex; } + }; + + /// Scoped lock idiom. + // Acquire the mutex here with a constructor call, then release with + // the destructor call in accordance with RAII style. + class __scoped_lock + { + public: + typedef __mutex __mutex_type; + + private: + __mutex_type& _M_device; + + __scoped_lock(const __scoped_lock&); + __scoped_lock& operator=(const __scoped_lock&); + + public: + explicit __scoped_lock(__mutex_type& __name) : _M_device(__name) + { _M_device.lock(); } + + ~__scoped_lock() throw() + { _M_device.unlock(); } + }; + +#ifdef __GTHREAD_HAS_COND + class __cond + { + private: +#if __GTHREADS && defined __GTHREAD_COND_INIT + __gthread_cond_t _M_cond = __GTHREAD_COND_INIT; +#else + __gthread_cond_t _M_cond; +#endif + + __cond(const __cond&); + __cond& operator=(const __cond&); + + public: + __cond() + { +#if __GTHREADS && ! defined __GTHREAD_COND_INIT + if (__gthread_active_p()) + __GTHREAD_COND_INIT_FUNCTION(&_M_cond); +#endif + } + +#if __GTHREADS && ! defined __GTHREAD_COND_INIT + ~__cond() + { + if (__gthread_active_p()) + __gthread_cond_destroy(&_M_cond); + } +#endif + + void broadcast() + { +#if __GTHREADS + if (__gthread_active_p()) + { + if (__gthread_cond_broadcast(&_M_cond) != 0) + __throw_concurrence_broadcast_error(); + } +#endif + } + + void wait(__mutex *mutex) + { +#if __GTHREADS + { + if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0) + __throw_concurrence_wait_error(); + } +#endif + } + + void wait_recursive(__recursive_mutex *mutex) + { +#if __GTHREADS + { + if (__gthread_cond_wait_recursive(&_M_cond, + mutex->gthread_recursive_mutex()) + != 0) + __throw_concurrence_wait_error(); + } +#endif + } + }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/ext/iterator b/template/sysroot/include/ext/iterator new file mode 100644 index 0000000..d3e5e7e --- /dev/null +++ b/template/sysroot/include/ext/iterator @@ -0,0 +1,116 @@ +// HP/SGI iterator extensions -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/iterator + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_ITERATOR +#define _EXT_ITERATOR 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // There are two signatures for distance. In addition to the one + // taking two iterators and returning a result, there is another + // taking two iterators and a reference-to-result variable, and + // returning nothing. The latter seems to be an SGI extension. + // -- pedwards + template + inline void + __distance(_InputIterator __first, _InputIterator __last, + _Distance& __n, std::input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + while (__first != __last) + { + ++__first; + ++__n; + } + } + + template + inline void + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Distance& __n, std::random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __n += __last - __first; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline void + distance(_InputIterator __first, _InputIterator __last, + _Distance& __n) + { + // concept requirements -- taken care of in __distance + __distance(__first, __last, __n, std::__iterator_category(__first)); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/template/sysroot/include/ext/numeric_traits.h b/template/sysroot/include/ext/numeric_traits.h new file mode 100644 index 0000000..b2723bf --- /dev/null +++ b/template/sysroot/include/ext/numeric_traits.h @@ -0,0 +1,241 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/numeric_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_NUMERIC_TRAITS +#define _EXT_NUMERIC_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Compile time constants for builtin types. + // In C++98 std::numeric_limits member functions are not constant expressions + // (that changed in C++11 with the addition of 'constexpr'). + // Even for C++11, this header is smaller than and can be used + // when only is_signed, digits, min, or max values are needed for integers, + // or is_signed, digits10, max_digits10, or max_exponent10 for floats. + + // Unlike __is_integer (and std::is_integral) this trait is true for + // non-standard built-in integer types such as __int128 and __int20. + template + struct __is_integer_nonstrict + : public std::__is_integer<_Tp> + { + using std::__is_integer<_Tp>::__value; + + // The number of bits in the value representation. + enum { __width = __value ? sizeof(_Tp) * __CHAR_BIT__ : 0 }; + }; + + template + struct __numeric_traits_integer + { +#if __cplusplus >= 201103L + static_assert(__is_integer_nonstrict<_Value>::__value, + "invalid specialization"); +#endif + + // NB: these two are also available in std::numeric_limits as compile + // time constants, but is big and we can avoid including it. + static const bool __is_signed = (_Value)(-1) < 0; + static const int __digits + = __is_integer_nonstrict<_Value>::__width - __is_signed; + + // The initializers must be constants so that __max and __min are too. + static const _Value __max = __is_signed + ? (((((_Value)1 << (__digits - 1)) - 1) << 1) + 1) + : ~(_Value)0; + static const _Value __min = __is_signed ? -__max - 1 : (_Value)0; + }; + + template + const _Value __numeric_traits_integer<_Value>::__min; + + template + const _Value __numeric_traits_integer<_Value>::__max; + + template + const bool __numeric_traits_integer<_Value>::__is_signed; + + template + const int __numeric_traits_integer<_Value>::__digits; + + // Enable __numeric_traits_integer for types where the __is_integer_nonstrict + // primary template doesn't give the right answer. +#define _GLIBCXX_INT_N_TRAITS(T, WIDTH) \ + __extension__ \ + template<> struct __is_integer_nonstrict \ + { \ + enum { __value = 1 }; \ + typedef std::__true_type __type; \ + enum { __width = WIDTH }; \ + }; \ + __extension__ \ + template<> struct __is_integer_nonstrict \ + { \ + enum { __value = 1 }; \ + typedef std::__true_type __type; \ + enum { __width = WIDTH }; \ + }; + + // We need to specify the width for some __intNN types because they + // have padding bits, e.g. the object representation of __int20 has 32 bits, + // but its width (number of bits in the value representation) is only 20. +#if defined __GLIBCXX_TYPE_INT_N_0 && __GLIBCXX_BITSIZE_INT_N_0 % __CHAR_BIT__ + _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0) +#endif +#if defined __GLIBCXX_TYPE_INT_N_1 && __GLIBCXX_BITSIZE_INT_N_1 % __CHAR_BIT__ + _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1) +#endif +#if defined __GLIBCXX_TYPE_INT_N_2 && __GLIBCXX_BITSIZE_INT_N_2 % __CHAR_BIT__ + _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2) +#endif +#if defined __GLIBCXX_TYPE_INT_N_3 && __GLIBCXX_BITSIZE_INT_N_3 % __CHAR_BIT__ + _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3) +#endif + +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // In strict modes __is_integer<__int128> is false, + // but we still want to define __numeric_traits_integer<__int128>. + _GLIBCXX_INT_N_TRAITS(__int128, 128) +#endif + +#undef _GLIBCXX_INT_N_TRAITS + +#if __cplusplus >= 201103L + /// Convenience alias for __numeric_traits. + template + using __int_traits = __numeric_traits_integer<_Tp>; +#endif + +#define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \ + (std::__are_same<_Tp, float>::__value ? _Fval \ + : std::__are_same<_Tp, double>::__value ? _Dval : _LDval) + +#define __glibcxx_max_digits10(_Tp) \ + (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \ + __LDBL_MANT_DIG__) * 643L / 2136) + +#define __glibcxx_digits10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__) + +#define __glibcxx_max_exponent10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \ + __LDBL_MAX_10_EXP__) + + // N.B. this only supports float, double and long double (no __float128 etc.) + template + struct __numeric_traits_floating + { + // Only floating point types. See N1822. + static const int __max_digits10 = __glibcxx_max_digits10(_Value); + + // See above comment... + static const bool __is_signed = true; + static const int __digits10 = __glibcxx_digits10(_Value); + static const int __max_exponent10 = __glibcxx_max_exponent10(_Value); + }; + + template + const int __numeric_traits_floating<_Value>::__max_digits10; + + template + const bool __numeric_traits_floating<_Value>::__is_signed; + + template + const int __numeric_traits_floating<_Value>::__digits10; + + template + const int __numeric_traits_floating<_Value>::__max_exponent10; + +#undef __glibcxx_floating +#undef __glibcxx_max_digits10 +#undef __glibcxx_digits10 +#undef __glibcxx_max_exponent10 + + template + struct __numeric_traits + : public __numeric_traits_integer<_Value> + { }; + + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; + + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; + + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; + +#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT +# if defined __LONG_DOUBLE_IEEE128__ + // long double is __ieee128, define traits for __ibm128 + template<> + struct __numeric_traits_floating<__ibm128> + { + static const int __max_digits10 = 33; + static const bool __is_signed = true; + static const int __digits10 = 31; + static const int __max_exponent10 = 308; + }; + template<> + struct __numeric_traits<__ibm128> + : public __numeric_traits_floating<__ibm128> + { }; +# elif defined __LONG_DOUBLE_IBM128__ + // long double is __ibm128, define traits for __ieee128 + template<> + struct __numeric_traits_floating<__ieee128> + { + static const int __max_digits10 = 36; + static const bool __is_signed = true; + static const int __digits10 = 33; + static const int __max_exponent10 = 4932; + }; + template<> + struct __numeric_traits<__ieee128> + : public __numeric_traits_floating<__ieee128> + { }; +# endif +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/template/sysroot/include/ext/pointer.h b/template/sysroot/include/ext/pointer.h new file mode 100644 index 0000000..534b3c7 --- /dev/null +++ b/template/sysroot/include/ext/pointer.h @@ -0,0 +1,611 @@ +// Custom pointer adapter and sample storage policies + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file ext/pointer.h + * This file is a GNU extension to the Standard C++ Library. + * + * @author Bob Walters + * + * Provides reusable _Pointer_adapter for assisting in the development of + * custom pointer types that can be used with the standard containers via + * the allocator::pointer and allocator::const_pointer typedefs. + */ + +#ifndef _POINTER_H +#define _POINTER_H 1 + +#pragma GCC system_header + +#if _GLIBCXX_HOSTED +# include +#endif + +#include +#include +#include +#if __cplusplus >= 201103L +# include +# include +#endif +#if __cplusplus > 201703L +# include // for indirectly_readable_traits +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A storage policy for use with _Pointer_adapter<> which yields a + * standard pointer. + * + * A _Storage_policy is required to provide 4 things: + * 1) A get() API for returning the stored pointer value. + * 2) An set() API for storing a pointer value. + * 3) An element_type typedef to define the type this points to. + * 4) An operator<() to support pointer comparison. + * 5) An operator==() to support pointer comparison. + */ + template + class _Std_pointer_impl + { + public: + // the type this pointer points to. + typedef _Tp element_type; + + // A method to fetch the pointer value as a standard T* value; + inline _Tp* + get() const + { return _M_value; } + + // A method to set the pointer value, from a standard T* value; + inline void + set(element_type* __arg) + { _M_value = __arg; } + + // Comparison of pointers + inline bool + operator<(const _Std_pointer_impl& __rarg) const + { return (_M_value < __rarg._M_value); } + + inline bool + operator==(const _Std_pointer_impl& __rarg) const + { return (_M_value == __rarg._M_value); } + + private: + element_type* _M_value; + }; + + /** + * @brief A storage policy for use with _Pointer_adapter<> which stores + * the pointer's address as an offset value which is relative to + * its own address. + * + * This is intended for pointers within shared memory regions which + * might be mapped at different addresses by different processes. + * For null pointers, a value of 1 is used. (0 is legitimate + * sometimes for nodes in circularly linked lists) This value was + * chosen as the least likely to generate an incorrect null, As + * there is no reason why any normal pointer would point 1 byte into + * its own pointer address. + */ + template + class _Relative_pointer_impl + { + public: + typedef _Tp element_type; + + _Tp* + get() const + { + if (_M_diff == 1) + return 0; + else + return reinterpret_cast<_Tp*>(reinterpret_cast(this) + + _M_diff); + } + + void + set(_Tp* __arg) + { + if (!__arg) + _M_diff = 1; + else + _M_diff = reinterpret_cast(__arg) + - reinterpret_cast(this); + } + + // Comparison of pointers + inline bool + operator<(const _Relative_pointer_impl& __rarg) const + { return (reinterpret_cast(this->get()) + < reinterpret_cast(__rarg.get())); } + + inline bool + operator==(const _Relative_pointer_impl& __rarg) const + { return (reinterpret_cast(this->get()) + == reinterpret_cast(__rarg.get())); } + + private: + typedef __UINTPTR_TYPE__ uintptr_t; + uintptr_t _M_diff; + }; + + /** + * Relative_pointer_impl needs a specialization for const T because of + * the casting done during pointer arithmetic. + */ + template + class _Relative_pointer_impl + { + public: + typedef const _Tp element_type; + + const _Tp* + get() const + { + if (_M_diff == 1) + return 0; + else + return reinterpret_cast + (reinterpret_cast(this) + _M_diff); + } + + void + set(const _Tp* __arg) + { + if (!__arg) + _M_diff = 1; + else + _M_diff = reinterpret_cast(__arg) + - reinterpret_cast(this); + } + + // Comparison of pointers + inline bool + operator<(const _Relative_pointer_impl& __rarg) const + { return (reinterpret_cast(this->get()) + < reinterpret_cast(__rarg.get())); } + + inline bool + operator==(const _Relative_pointer_impl& __rarg) const + { return (reinterpret_cast(this->get()) + == reinterpret_cast(__rarg.get())); } + + private: + typedef __UINTPTR_TYPE__ uintptr_t; + uintptr_t _M_diff; + }; + + /** + * The specialization on this type helps resolve the problem of + * reference to void, and eliminates the need to specialize + * _Pointer_adapter for cases of void*, const void*, and so on. + */ + struct _Invalid_type { }; + + template + struct _Reference_type + { typedef _Tp& reference; }; + + template<> + struct _Reference_type + { typedef _Invalid_type& reference; }; + + template<> + struct _Reference_type + { typedef const _Invalid_type& reference; }; + + template<> + struct _Reference_type + { typedef volatile _Invalid_type& reference; }; + + template<> + struct _Reference_type + { typedef const volatile _Invalid_type& reference; }; + + /** + * This structure accommodates the way in which + * std::iterator_traits<> is normally specialized for const T*, so + * that value_type is still T. + */ + template + struct _Unqualified_type + { typedef _Tp type; }; + + template + struct _Unqualified_type + { typedef _Tp type; }; + + /** + * The following provides an 'alternative pointer' that works with + * the containers when specified as the pointer typedef of the + * allocator. + * + * The pointer type used with the containers doesn't have to be this + * class, but it must support the implicit conversions, pointer + * arithmetic, comparison operators, etc. that are supported by this + * class, and avoid raising compile-time ambiguities. Because + * creating a working pointer can be challenging, this pointer + * template was designed to wrapper an easier storage policy type, + * so that it becomes reusable for creating other pointer types. + * + * A key point of this class is also that it allows container + * writers to 'assume' Allocator::pointer is a typedef for a normal + * pointer. This class supports most of the conventions of a true + * pointer, and can, for instance handle implicit conversion to + * const and base class pointer types. The only impositions on + * container writers to support extended pointers are: 1) use the + * Allocator::pointer typedef appropriately for pointer types. 2) + * if you need pointer casting, use the __pointer_cast<> functions + * from ext/cast.h. This allows pointer cast operations to be + * overloaded as necessary by custom pointers. + * + * Note: The const qualifier works with this pointer adapter as + * follows: + * + * _Tp* == _Pointer_adapter<_Std_pointer_impl<_Tp> >; + * const _Tp* == _Pointer_adapter<_Std_pointer_impl >; + * _Tp* const == const _Pointer_adapter<_Std_pointer_impl<_Tp> >; + * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl >; + */ + template + class _Pointer_adapter : public _Storage_policy + { + public: + typedef typename _Storage_policy::element_type element_type; + + // These are needed for iterator_traits + typedef std::random_access_iterator_tag iterator_category; + typedef typename _Unqualified_type::type value_type; + typedef std::ptrdiff_t difference_type; + typedef _Pointer_adapter pointer; + typedef typename _Reference_type::reference reference; + + // Reminder: 'const' methods mean that the method is valid when the + // pointer is immutable, and has nothing to do with whether the + // 'pointee' is const. + + // Default Constructor (Convert from element_type*) + _Pointer_adapter(element_type* __arg = 0) + { _Storage_policy::set(__arg); } + + // Copy constructor from _Pointer_adapter of same type. + _Pointer_adapter(const _Pointer_adapter& __arg) + { _Storage_policy::set(__arg.get()); } + + // Convert from _Up* if conversion to element_type* is valid. + template + _Pointer_adapter(_Up* __arg) + { _Storage_policy::set(__arg); } + + // Conversion from another _Pointer_adapter if _Up if static cast is + // valid. + template + _Pointer_adapter(const _Pointer_adapter<_Up>& __arg) + { _Storage_policy::set(__arg.get()); } + + // Destructor + ~_Pointer_adapter() { } + + // Assignment operator + _Pointer_adapter& + operator=(const _Pointer_adapter& __arg) + { + _Storage_policy::set(__arg.get()); + return *this; + } + + template + _Pointer_adapter& + operator=(const _Pointer_adapter<_Up>& __arg) + { + _Storage_policy::set(__arg.get()); + return *this; + } + + template + _Pointer_adapter& + operator=(_Up* __arg) + { + _Storage_policy::set(__arg); + return *this; + } + + // Operator*, returns element_type& + inline reference + operator*() const + { return *(_Storage_policy::get()); } + + // Operator->, returns element_type* + inline element_type* + operator->() const + { return _Storage_policy::get(); } + + // Operator[], returns a element_type& to the item at that loc. + inline reference + operator[](std::ptrdiff_t __index) const + { return _Storage_policy::get()[__index]; } + + // To allow implicit conversion to "bool", for "if (ptr)..." +#if __cplusplus >= 201103L + explicit operator bool() const { return _Storage_policy::get() != 0; } +#else + private: + typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const; + + public: + operator __unspecified_bool_type() const + { + return _Storage_policy::get() == 0 ? 0 : + &_Pointer_adapter::operator->; + } + + // ! operator (for: if (!ptr)...) + inline bool + operator!() const + { return (_Storage_policy::get() == 0); } +#endif + + // Pointer differences + inline friend std::ptrdiff_t + operator-(const _Pointer_adapter& __lhs, element_type* __rhs) + { return (__lhs.get() - __rhs); } + + inline friend std::ptrdiff_t + operator-(element_type* __lhs, const _Pointer_adapter& __rhs) + { return (__lhs - __rhs.get()); } + + template + inline friend std::ptrdiff_t + operator-(const _Pointer_adapter& __lhs, _Up* __rhs) + { return (__lhs.get() - __rhs); } + + template + inline friend std::ptrdiff_t + operator-(_Up* __lhs, const _Pointer_adapter& __rhs) + { return (__lhs - __rhs.get()); } + + template + inline std::ptrdiff_t + operator-(const _Pointer_adapter<_Up>& __rhs) const + { return (_Storage_policy::get() - __rhs.get()); } + + // Pointer math + // Note: There is a reason for all this overloading based on different + // integer types. In some libstdc++-v3 test cases, a templated + // operator+ is declared which can match any types. This operator + // tends to "steal" the recognition of _Pointer_adapter's own operator+ + // unless the integer type matches perfectly. + +#define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \ + inline friend _Pointer_adapter \ + operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \ + { return _Pointer_adapter(__lhs.get() + __offset); } \ +\ + inline friend _Pointer_adapter \ + operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \ + { return _Pointer_adapter(__rhs.get() + __offset); } \ +\ + inline friend _Pointer_adapter \ + operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \ + { return _Pointer_adapter(__lhs.get() - __offset); } \ +\ + inline _Pointer_adapter& \ + operator+=(INT_TYPE __offset) \ + { \ + _Storage_policy::set(_Storage_policy::get() + __offset); \ + return *this; \ + } \ +\ + inline _Pointer_adapter& \ + operator-=(INT_TYPE __offset) \ + { \ + _Storage_policy::set(_Storage_policy::get() - __offset); \ + return *this; \ + } \ +// END of _CXX_POINTER_ARITH_OPERATOR_SET macro + + // Expand into the various pointer arithmetic operators needed. + _CXX_POINTER_ARITH_OPERATOR_SET(short); + _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short); + _CXX_POINTER_ARITH_OPERATOR_SET(int); + _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int); + _CXX_POINTER_ARITH_OPERATOR_SET(long); + _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long); +#ifdef _GLIBCXX_USE_LONG_LONG + _CXX_POINTER_ARITH_OPERATOR_SET(long long); + _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long); +#endif + + // Mathematical Manipulators + inline _Pointer_adapter& + operator++() + { + _Storage_policy::set(_Storage_policy::get() + 1); + return *this; + } + + inline _Pointer_adapter + operator++(int) + { + _Pointer_adapter __tmp(*this); + _Storage_policy::set(_Storage_policy::get() + 1); + return __tmp; + } + + inline _Pointer_adapter& + operator--() + { + _Storage_policy::set(_Storage_policy::get() - 1); + return *this; + } + + inline _Pointer_adapter + operator--(int) + { + _Pointer_adapter __tmp(*this); + _Storage_policy::set(_Storage_policy::get() - 1); + return __tmp; + } + +#if __cpp_lib_three_way_comparison + friend std::strong_ordering + operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs) + noexcept + { return __lhs.get() <=> __rhs.get(); } +#endif + }; // class _Pointer_adapter + + +#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \ + template \ + inline bool \ + operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \ + { return __lhs.get() OPERATOR __rhs; } \ +\ + template \ + inline bool \ + operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \ + { return __lhs OPERATOR __rhs.get(); } \ +\ + template \ + inline bool \ + operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \ + const _Pointer_adapter<_Tp2>& __rhs) \ + { return __lhs.get() OPERATOR __rhs.get(); } \ +\ +// End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro + + // Expand into the various comparison operators needed. + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==) + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=) + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<) + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=) + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>) + _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=) + + // These are here for expressions like "ptr == 0", "ptr != 0" + template + inline bool + operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs) + { return __lhs.get() == reinterpret_cast(__rhs); } + + template + inline bool + operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs) + { return __rhs.get() == reinterpret_cast(__lhs); } + + template + inline bool + operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs) + { return __lhs.get() != reinterpret_cast(__rhs); } + + template + inline bool + operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs) + { return __rhs.get() != reinterpret_cast(__lhs); } + + /** + * Comparison operators for _Pointer_adapter defer to the base class' + * comparison operators, when possible. + */ + template + inline bool + operator==(const _Pointer_adapter<_Tp>& __lhs, + const _Pointer_adapter<_Tp>& __rhs) + { return __lhs._Tp::operator==(__rhs); } + + template + inline bool + operator<=(const _Pointer_adapter<_Tp>& __lhs, + const _Pointer_adapter<_Tp>& __rhs) + { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); } + + template + inline bool + operator!=(const _Pointer_adapter<_Tp>& __lhs, + const _Pointer_adapter<_Tp>& __rhs) + { return !(__lhs._Tp::operator==(__rhs)); } + + template + inline bool + operator>(const _Pointer_adapter<_Tp>& __lhs, + const _Pointer_adapter<_Tp>& __rhs) + { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); } + + template + inline bool + operator>=(const _Pointer_adapter<_Tp>& __lhs, + const _Pointer_adapter<_Tp>& __rhs) + { return !(__lhs._Tp::operator<(__rhs)); } + +#if _GLIBCXX_HOSTED + template + inline std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const _Pointer_adapter<_StoreT>& __p) + { return (__os << __p.get()); } +#endif // HOSTED + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>> + { + /// The pointer type + typedef __gnu_cxx::_Pointer_adapter<_Storage_policy> pointer; + /// The type pointed to + typedef typename pointer::element_type element_type; + /// Type used to represent the difference between two pointers + typedef typename pointer::difference_type difference_type; + + template + using rebind = typename __gnu_cxx::_Pointer_adapter< + typename pointer_traits<_Storage_policy>::template rebind<_Up>>; + + static pointer pointer_to(typename pointer::reference __r) noexcept + { return pointer(std::addressof(__r)); } + }; + +#if __cpp_lib_concepts + template + struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>> + { + using value_type + = typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type; + }; +#endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif + +#endif // _POINTER_H diff --git a/template/sysroot/include/ext/type_traits.h b/template/sysroot/include/ext/type_traits.h new file mode 100644 index 0000000..75d7edf --- /dev/null +++ b/template/sysroot/include/ext/type_traits.h @@ -0,0 +1,273 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/type_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_TYPE_TRAITS +#define _EXT_TYPE_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +extern "C++" { + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Define a nested type if some predicate holds. + template + struct __enable_if + { }; + + template + struct __enable_if + { typedef _Tp __type; }; + + + // Conditional expression for types. If true, first, if false, second. + template + struct __conditional_type + { typedef _Iftrue __type; }; + + template + struct __conditional_type + { typedef _Iffalse __type; }; + + + // Given an integral builtin type, return the corresponding unsigned type. + template + struct __add_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned short __type; }; + + template<> + struct __add_unsigned + { typedef unsigned int __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long long __type; }; + + // Declare but don't define. + template<> + struct __add_unsigned; + + template<> + struct __add_unsigned; + + + // Given an integral builtin type, return the corresponding signed type. + template + struct __remove_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef short __type; }; + + template<> + struct __remove_unsigned + { typedef int __type; }; + + template<> + struct __remove_unsigned + { typedef long __type; }; + + template<> + struct __remove_unsigned + { typedef long long __type; }; + + // Declare but don't define. + template<> + struct __remove_unsigned; + + template<> + struct __remove_unsigned; + + + // For use in string and vstring. + template + _GLIBCXX_CONSTEXPR + inline bool + __is_null_pointer(_Type* __ptr) + { return __ptr == 0; } + + template + _GLIBCXX_CONSTEXPR + inline bool + __is_null_pointer(_Type) + { return false; } + +#if __cplusplus >= 201103L + constexpr bool + __is_null_pointer(std::nullptr_t) + { return true; } +#endif + + // For arithmetic promotions in and + + template::__value> + struct __promote + { typedef double __type; }; + + // No nested __type member for non-integer non-floating point types, + // allows this type to be used for SFINAE to constrain overloads in + // and to only the intended types. + template + struct __promote<_Tp, false> + { }; + + template<> + struct __promote + { typedef long double __type; }; + + template<> + struct __promote + { typedef double __type; }; + + template<> + struct __promote + { typedef float __type; }; + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __promote<_Float16> + { typedef _Float16 __type; }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __promote<_Float32> + { typedef _Float32 __type; }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __promote<_Float64> + { typedef _Float64 __type; }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __promote<_Float128> + { typedef _Float128 __type; }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __promote<__gnu_cxx::__bfloat16_t> + { typedef __gnu_cxx::__bfloat16_t __type; }; +#endif + +#if __cpp_fold_expressions + + template + using __promoted_t = decltype((typename __promote<_Tp>::__type(0) + ...)); + + // Deducing the promoted type is done by __promoted_t<_Tp...>, + // then __promote is used to provide the nested __type member. + template + using __promote_2 = __promote<__promoted_t<_Tp, _Up>>; + + template + using __promote_3 = __promote<__promoted_t<_Tp, _Up, _Vp>>; + + template + using __promote_4 = __promote<__promoted_t<_Tp, _Up, _Vp, _Wp>>; + +#else + + template::__type, + typename _Up2 = typename __promote<_Up>::__type> + struct __promote_2 + { + typedef __typeof__(_Tp2() + _Up2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type> + struct __promote_3 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type, + typename _Wp2 = typename __promote<_Wp>::__type> + struct __promote_4 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; + }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif diff --git a/template/sysroot/include/ext/typelist.h b/template/sysroot/include/ext/typelist.h new file mode 100644 index 0000000..27cb643 --- /dev/null +++ b/template/sysroot/include/ext/typelist.h @@ -0,0 +1,538 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. + +// Permission to use, copy, modify, sell, and distribute this software +// is hereby granted without fee, provided that the above copyright +// notice appears in all copies, and that both that copyright notice and +// this permission notice appear in supporting documentation. None of +// the above authors, nor IBM Haifa Research Laboratories, make any +// representation about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. + +/** + * @file ext/typelist.h + * This file is a GNU extension to the Standard C++ Library. + * + * Contains typelist_chain definitions. + * Typelists are an idea by Andrei Alexandrescu. + */ + +#ifndef _TYPELIST_H +#define _TYPELIST_H 1 + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @namespace __gnu_cxx::typelist + * @brief GNU typelist extensions for public compile-time use. +*/ +namespace typelist +{ + struct null_type { }; + + template + struct node + { + typedef Root root; + }; + + // Forward declarations of functors. + template + struct chain + { + typedef Hd head; + typedef Typelist tail; + }; + + // Apply all typelist types to unary functor. + template + void + apply(Fn&, Typelist); + + /// Apply all typelist types to generator functor. + template + void + apply_generator(Gn&, Typelist); + + // Apply all typelist types and values to generator functor. + template + void + apply_generator(Gn&, TypelistT, TypelistV); + + template + struct append; + + template + struct append_typelist; + + template + struct contains; + + template class Pred> + struct filter; + + template + struct at_index; + + template class Transform> + struct transform; + + template + struct flatten; + + template + struct from_first; + + template + struct create1; + + template + struct create2; + + template + struct create3; + + template + struct create4; + + template + struct create5; + + template + struct create6; + +namespace detail +{ + template + struct apply_; + + template + struct apply_ > + { + void + operator()(Fn& f) + { + f.operator()(Hd()); + apply_ next; + next(f); + } + }; + + template + struct apply_ + { + void + operator()(Fn&) { } + }; + + template + struct apply_generator1_; + + template + struct apply_generator1_ > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator1_ next; + next(g); + } + }; + + template + struct apply_generator1_ + { + void + operator()(Gn&) { } + }; + + template + struct apply_generator2_; + + template + struct apply_generator2_, chain > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator2_ next; + next(g); + } + }; + + template + struct apply_generator2_ + { + void + operator()(Gn&) { } + }; + + template + struct append_; + + template + struct append_, Typelist_Chain> + { + private: + typedef append_ append_type; + + public: + typedef chain type; + }; + + template + struct append_ + { + typedef Typelist_Chain type; + }; + + template + struct append_, null_type> + { + typedef chain type; + }; + + template<> + struct append_ + { + typedef null_type type; + }; + + template + struct append_typelist_; + + template + struct append_typelist_ > + { + typedef chain type; + }; + + template + struct append_typelist_ > + { + private: + typedef typename append_typelist_::type rest_type; + + public: + typedef typename append >::type::root type; + }; + + template + struct contains_; + + template + struct contains_ + { + enum + { + value = false + }; + }; + + template + struct contains_, T> + { + enum + { + value = contains_::value + }; + }; + + template + struct contains_, T> + { + enum + { + value = true + }; + }; + + template class Pred> + struct chain_filter_; + + template class Pred> + struct chain_filter_ + { + typedef null_type type; + }; + + template class Pred> + struct chain_filter_, Pred> + { + private: + enum + { + include_hd = Pred::value + }; + + typedef typename chain_filter_::type rest_type; + typedef chain chain_type; + + public: + typedef typename __conditional_type::__type type; + }; + + template + struct chain_at_index_; + + template + struct chain_at_index_, 0> + { + typedef Hd type; + }; + + template + struct chain_at_index_, i> + { + typedef typename chain_at_index_::type type; + }; + + template class Transform> + struct chain_transform_; + + template class Transform> + struct chain_transform_ + { + typedef null_type type; + }; + + template class Transform> + struct chain_transform_, Transform> + { + private: + typedef typename chain_transform_::type rest_type; + typedef typename Transform::type transform_type; + + public: + typedef chain type; + }; + + template + struct chain_flatten_; + + template + struct chain_flatten_ > + { + typedef typename Hd_Tl::root type; + }; + + template + struct chain_flatten_ > + { + private: + typedef typename chain_flatten_::type rest_type; + typedef append > append_type; + public: + typedef typename append_type::type::root type; + }; +} // namespace detail + +#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain + + template + void + apply(Fn& fn, Typelist) + { + detail::apply_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, Typelist) + { + detail::apply_generator1_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, TypelistT, TypelistV) + { + typedef typename TypelistT::root rootT; + typedef typename TypelistV::root rootV; + detail::apply_generator2_ a; + a(fn); + } + + template + struct append + { + private: + typedef typename Typelist0::root root0_type; + typedef typename Typelist1::root root1_type; + typedef detail::append_ append_type; + + public: + typedef node type; + }; + + template + struct append_typelist + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef detail::append_typelist_ append_type; + + public: + typedef node type; + }; + + template + struct contains + { + private: + typedef typename Typelist::root root_type; + + public: + enum + { + value = detail::contains_::value + }; + }; + + template class Pred> + struct filter + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_filter_ filter_type; + + public: + typedef node type; + }; + + template + struct at_index + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_at_index_ index_type; + + public: + typedef typename index_type::type type; + }; + + template class Transform> + struct transform + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_transform_ transform_type; + + public: + typedef node type; + }; + + template + struct flatten + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef typename detail::chain_flatten_::type flatten_type; + + public: + typedef node type; + }; + + template + struct from_first + { + private: + typedef typename at_index::type first_type; + + public: + typedef node > type; + }; + + template + struct create1 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; + }; + + template + struct create2 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; + }; + + template + struct create3 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; + }; + + template + struct create4 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; + }; + + template + struct create5 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; + }; + + template + struct create6 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; + }; +} // namespace typelist +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#endif diff --git a/template/sysroot/include/f16cintrin.h b/template/sysroot/include/f16cintrin.h new file mode 100644 index 0000000..e888837 --- /dev/null +++ b/template/sysroot/include/f16cintrin.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include or instead." +#endif + +#ifndef _F16CINTRIN_H_INCLUDED +#define _F16CINTRIN_H_INCLUDED + +#ifndef __F16C__ +#pragma GCC push_options +#pragma GCC target("f16c") +#define __DISABLE_F16C__ +#endif /* __F16C__ */ + +extern __inline float __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_cvtsh_ss (unsigned short __S) +{ + __v8hi __H = __extension__ (__v8hi){ (short) __S, 0, 0, 0, 0, 0, 0, 0 }; + __v4sf __A = __builtin_ia32_vcvtph2ps (__H); + return __builtin_ia32_vec_ext_v4sf (__A, 0); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtph_ps (__m128i __A) +{ + return (__m128) __builtin_ia32_vcvtph2ps ((__v8hi) __A); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtph_ps (__m128i __A) +{ + return (__m256) __builtin_ia32_vcvtph2ps256 ((__v8hi) __A); +} + +#ifdef __OPTIMIZE__ +extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_cvtss_sh (float __F, const int __I) +{ + __v4sf __A = __extension__ (__v4sf){ __F, 0, 0, 0 }; + __v8hi __H = __builtin_ia32_vcvtps2ph (__A, __I); + return (unsigned short) __builtin_ia32_vec_ext_v8hi (__H, 0); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_ph (__m128 __A, const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph ((__v4sf) __A, __I); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtps_ph (__m256 __A, const int __I) +{ + return (__m128i) __builtin_ia32_vcvtps2ph256 ((__v8sf) __A, __I); +} +#else +#define _cvtss_sh(__F, __I) \ + (__extension__ \ + ({ \ + __v4sf __A = __extension__ (__v4sf){ __F, 0, 0, 0 }; \ + __v8hi __H = __builtin_ia32_vcvtps2ph (__A, __I); \ + (unsigned short) __builtin_ia32_vec_ext_v8hi (__H, 0); \ + })) + +#define _mm_cvtps_ph(A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph ((__v4sf)(__m128) (A), (int) (I))) + +#define _mm256_cvtps_ph(A, I) \ + ((__m128i) __builtin_ia32_vcvtps2ph256 ((__v8sf)(__m256) (A), (int) (I))) +#endif /* __OPTIMIZE */ + +#ifdef __DISABLE_F16C__ +#undef __DISABLE_F16C__ +#pragma GCC pop_options +#endif /* __DISABLE_F16C__ */ + +#endif /* _F16CINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/float.h b/template/sysroot/include/float.h new file mode 100644 index 0000000..47f41f9 --- /dev/null +++ b/template/sysroot/include/float.h @@ -0,0 +1,631 @@ +/* Copyright (C) 2002-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 5.2.4.2.2 Characteristics of floating types + */ + +#ifndef _FLOAT_H___ +#define _FLOAT_H___ + +/* Radix of exponent representation, b. */ +#undef FLT_RADIX +#define FLT_RADIX __FLT_RADIX__ + +/* Number of base-FLT_RADIX digits in the significand, p. */ +#undef FLT_MANT_DIG +#undef DBL_MANT_DIG +#undef LDBL_MANT_DIG +#define FLT_MANT_DIG __FLT_MANT_DIG__ +#define DBL_MANT_DIG __DBL_MANT_DIG__ +#define LDBL_MANT_DIG __LDBL_MANT_DIG__ + +/* Number of decimal digits, q, such that any floating-point number with q + decimal digits can be rounded into a floating-point number with p radix b + digits and back again without change to the q decimal digits, + + p * log10(b) if b is a power of 10 + floor((p - 1) * log10(b)) otherwise +*/ +#undef FLT_DIG +#undef DBL_DIG +#undef LDBL_DIG +#define FLT_DIG __FLT_DIG__ +#define DBL_DIG __DBL_DIG__ +#define LDBL_DIG __LDBL_DIG__ + +/* Minimum int x such that FLT_RADIX**(x-1) is a normalized float, emin */ +#undef FLT_MIN_EXP +#undef DBL_MIN_EXP +#undef LDBL_MIN_EXP +#define FLT_MIN_EXP __FLT_MIN_EXP__ +#define DBL_MIN_EXP __DBL_MIN_EXP__ +#define LDBL_MIN_EXP __LDBL_MIN_EXP__ + +/* Minimum negative integer such that 10 raised to that power is in the + range of normalized floating-point numbers, + + ceil(log10(b) * (emin - 1)) +*/ +#undef FLT_MIN_10_EXP +#undef DBL_MIN_10_EXP +#undef LDBL_MIN_10_EXP +#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ +#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ +#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ + +/* Maximum int x such that FLT_RADIX**(x-1) is a representable float, emax. */ +#undef FLT_MAX_EXP +#undef DBL_MAX_EXP +#undef LDBL_MAX_EXP +#define FLT_MAX_EXP __FLT_MAX_EXP__ +#define DBL_MAX_EXP __DBL_MAX_EXP__ +#define LDBL_MAX_EXP __LDBL_MAX_EXP__ + +/* Maximum integer such that 10 raised to that power is in the range of + representable finite floating-point numbers, + + floor(log10((1 - b**-p) * b**emax)) +*/ +#undef FLT_MAX_10_EXP +#undef DBL_MAX_10_EXP +#undef LDBL_MAX_10_EXP +#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ +#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +/* Maximum representable finite floating-point number, + + (1 - b**-p) * b**emax +*/ +#undef FLT_MAX +#undef DBL_MAX +#undef LDBL_MAX +#define FLT_MAX __FLT_MAX__ +#define DBL_MAX __DBL_MAX__ +#define LDBL_MAX __LDBL_MAX__ + +/* The difference between 1 and the least value greater than 1 that is + representable in the given floating point type, b**1-p. */ +#undef FLT_EPSILON +#undef DBL_EPSILON +#undef LDBL_EPSILON +#define FLT_EPSILON __FLT_EPSILON__ +#define DBL_EPSILON __DBL_EPSILON__ +#define LDBL_EPSILON __LDBL_EPSILON__ + +/* Minimum normalized positive floating-point number, b**(emin - 1). */ +#undef FLT_MIN +#undef DBL_MIN +#undef LDBL_MIN +#define FLT_MIN __FLT_MIN__ +#define DBL_MIN __DBL_MIN__ +#define LDBL_MIN __LDBL_MIN__ + +/* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown. */ +/* ??? This is supposed to change with calls to fesetround in . */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \ + || (defined (__cplusplus) && __cplusplus >= 201103L) +/* The floating-point expression evaluation method. The precise + definitions of these values are generalised to include support for + the interchange and extended types defined in ISO/IEC TS 18661-3. + Prior to this (for C99/C11) the definitions were: + + -1 indeterminate + 0 evaluate all operations and constants just to the range and + precision of the type + 1 evaluate operations and constants of type float and double + to the range and precision of the double type, evaluate + long double operations and constants to the range and + precision of the long double type + 2 evaluate all operations and constants to the range and + precision of the long double type + + The TS 18661-3 definitions are: + + -1 indeterminate + 0 evaluate all operations and constants, whose semantic type has + at most the range and precision of float, to the range and + precision of float; evaluate all other operations and constants + to the range and precision of the semantic type. + 1 evaluate all operations and constants, whose semantic type has + at most the range and precision of double, to the range and + precision of double; evaluate all other operations and constants + to the range and precision of the semantic type. + 2 evaluate all operations and constants, whose semantic type has + at most the range and precision of long double, to the range and + precision of long double; evaluate all other operations and + constants to the range and precision of the semantic type. + N where _FloatN is a supported interchange floating type + evaluate all operations and constants, whose semantic type has + at most the range and precision of the _FloatN type, to the + range and precision of the _FloatN type; evaluate all other + operations and constants to the range and precision of the + semantic type. + N + 1, where _FloatNx is a supported extended floating type + evaluate operations and constants, whose semantic type has at + most the range and precision of the _FloatNx type, to the range + and precision of the _FloatNx type; evaluate all other + operations and constants to the range and precision of the + semantic type. + + The compiler predefines two macros: + + __FLT_EVAL_METHOD__ + Which, depending on the value given for + -fpermitted-flt-eval-methods, may be limited to only those values + for FLT_EVAL_METHOD defined in C99/C11. + + __FLT_EVAL_METHOD_TS_18661_3__ + Which always permits the values for FLT_EVAL_METHOD defined in + ISO/IEC TS 18661-3. + + Here we want to use __FLT_EVAL_METHOD__, unless + __STDC_WANT_IEC_60559_TYPES_EXT__ is defined, in which case the user + is specifically asking for the ISO/IEC TS 18661-3 types, so we use + __FLT_EVAL_METHOD_TS_18661_3__. + + ??? This ought to change with the setting of the fp control word; + the value provided by the compiler assumes the widest setting. */ +#undef FLT_EVAL_METHOD +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD_TS_18661_3__ +#else +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +#endif + +/* Number of decimal digits, n, such that any floating-point number in the + widest supported floating type with pmax radix b digits can be rounded + to a floating-point number with n decimal digits and back again without + change to the value, + + pmax * log10(b) if b is a power of 10 + ceil(1 + pmax * log10(b)) otherwise +*/ +#undef DECIMAL_DIG +#define DECIMAL_DIG __DECIMAL_DIG__ + +#endif /* C99 */ + +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ + || (defined (__cplusplus) && __cplusplus >= 201703L) +/* Versions of DECIMAL_DIG for each floating-point type. */ +#undef FLT_DECIMAL_DIG +#undef DBL_DECIMAL_DIG +#undef LDBL_DECIMAL_DIG +#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ +#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ +#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ + +/* Whether types support subnormal numbers. */ +#undef FLT_HAS_SUBNORM +#undef DBL_HAS_SUBNORM +#undef LDBL_HAS_SUBNORM +#define FLT_HAS_SUBNORM __FLT_HAS_DENORM__ +#define DBL_HAS_SUBNORM __DBL_HAS_DENORM__ +#define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ + +/* Minimum positive values, including subnormals. */ +#undef FLT_TRUE_MIN +#undef DBL_TRUE_MIN +#undef LDBL_TRUE_MIN +#define FLT_TRUE_MIN __FLT_DENORM_MIN__ +#define DBL_TRUE_MIN __DBL_DENORM_MIN__ +#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__ + +#endif /* C11 */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +/* Maximum finite positive value with MANT_DIG digits in the + significand taking their maximum value. */ +#undef FLT_NORM_MAX +#undef DBL_NORM_MAX +#undef LDBL_NORM_MAX +#define FLT_NORM_MAX __FLT_NORM_MAX__ +#define DBL_NORM_MAX __DBL_NORM_MAX__ +#define LDBL_NORM_MAX __LDBL_NORM_MAX__ + +/* Whether each type matches an IEC 60559 format. */ +#undef FLT_IS_IEC_60559 +#undef DBL_IS_IEC_60559 +#undef LDBL_IS_IEC_60559 +#define FLT_IS_IEC_60559 __FLT_IS_IEC_60559__ +#define DBL_IS_IEC_60559 __DBL_IS_IEC_60559__ +#define LDBL_IS_IEC_60559 __LDBL_IS_IEC_60559__ + +/* Infinity in type float; not defined if infinity not supported. */ +#if __FLT_HAS_INFINITY__ +#undef INFINITY +#define INFINITY (__builtin_inff ()) +#endif + +/* Quiet NaN, if supported for float. */ +#if __FLT_HAS_QUIET_NAN__ +#undef NAN +#define NAN (__builtin_nanf ("")) +#endif + +/* Signaling NaN, if supported for each type. All formats supported + by GCC support either both quiet and signaling NaNs, or neither + kind of NaN. */ +#if __FLT_HAS_QUIET_NAN__ +#undef FLT_SNAN +#define FLT_SNAN (__builtin_nansf ("")) +#endif +#if __DBL_HAS_QUIET_NAN__ +#undef DBL_SNAN +#define DBL_SNAN (__builtin_nans ("")) +#endif +#if __LDBL_HAS_QUIET_NAN__ +#undef LDBL_SNAN +#define LDBL_SNAN (__builtin_nansl ("")) +#endif + +#endif /* C23 */ + +#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \ + || defined __STDC_WANT_IEC_60559_EXT__) +/* Number of decimal digits for which conversions between decimal + character strings and binary formats, in both directions, are + correctly rounded. */ +#define CR_DECIMAL_DIG __UINTMAX_MAX__ +#endif + +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +/* Constants for _FloatN and _FloatNx types from TS 18661-3. See + comments above for their semantics. */ + +#ifdef __FLT16_MANT_DIG__ +#undef FLT16_MANT_DIG +#define FLT16_MANT_DIG __FLT16_MANT_DIG__ +#undef FLT16_DIG +#define FLT16_DIG __FLT16_DIG__ +#undef FLT16_MIN_EXP +#define FLT16_MIN_EXP __FLT16_MIN_EXP__ +#undef FLT16_MIN_10_EXP +#define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__ +#undef FLT16_MAX_EXP +#define FLT16_MAX_EXP __FLT16_MAX_EXP__ +#undef FLT16_MAX_10_EXP +#define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__ +#undef FLT16_MAX +#define FLT16_MAX __FLT16_MAX__ +#undef FLT16_EPSILON +#define FLT16_EPSILON __FLT16_EPSILON__ +#undef FLT16_MIN +#define FLT16_MIN __FLT16_MIN__ +#undef FLT16_DECIMAL_DIG +#define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__ +#undef FLT16_TRUE_MIN +#define FLT16_TRUE_MIN __FLT16_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT16_SNAN +#define FLT16_SNAN (__builtin_nansf16 ("")) +#endif /* C23 */ +#endif /* __FLT16_MANT_DIG__. */ + +#ifdef __FLT32_MANT_DIG__ +#undef FLT32_MANT_DIG +#define FLT32_MANT_DIG __FLT32_MANT_DIG__ +#undef FLT32_DIG +#define FLT32_DIG __FLT32_DIG__ +#undef FLT32_MIN_EXP +#define FLT32_MIN_EXP __FLT32_MIN_EXP__ +#undef FLT32_MIN_10_EXP +#define FLT32_MIN_10_EXP __FLT32_MIN_10_EXP__ +#undef FLT32_MAX_EXP +#define FLT32_MAX_EXP __FLT32_MAX_EXP__ +#undef FLT32_MAX_10_EXP +#define FLT32_MAX_10_EXP __FLT32_MAX_10_EXP__ +#undef FLT32_MAX +#define FLT32_MAX __FLT32_MAX__ +#undef FLT32_EPSILON +#define FLT32_EPSILON __FLT32_EPSILON__ +#undef FLT32_MIN +#define FLT32_MIN __FLT32_MIN__ +#undef FLT32_DECIMAL_DIG +#define FLT32_DECIMAL_DIG __FLT32_DECIMAL_DIG__ +#undef FLT32_TRUE_MIN +#define FLT32_TRUE_MIN __FLT32_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT32_SNAN +#define FLT32_SNAN (__builtin_nansf32 ("")) +#endif /* C23 */ +#endif /* __FLT32_MANT_DIG__. */ + +#ifdef __FLT64_MANT_DIG__ +#undef FLT64_MANT_DIG +#define FLT64_MANT_DIG __FLT64_MANT_DIG__ +#undef FLT64_DIG +#define FLT64_DIG __FLT64_DIG__ +#undef FLT64_MIN_EXP +#define FLT64_MIN_EXP __FLT64_MIN_EXP__ +#undef FLT64_MIN_10_EXP +#define FLT64_MIN_10_EXP __FLT64_MIN_10_EXP__ +#undef FLT64_MAX_EXP +#define FLT64_MAX_EXP __FLT64_MAX_EXP__ +#undef FLT64_MAX_10_EXP +#define FLT64_MAX_10_EXP __FLT64_MAX_10_EXP__ +#undef FLT64_MAX +#define FLT64_MAX __FLT64_MAX__ +#undef FLT64_EPSILON +#define FLT64_EPSILON __FLT64_EPSILON__ +#undef FLT64_MIN +#define FLT64_MIN __FLT64_MIN__ +#undef FLT64_DECIMAL_DIG +#define FLT64_DECIMAL_DIG __FLT64_DECIMAL_DIG__ +#undef FLT64_TRUE_MIN +#define FLT64_TRUE_MIN __FLT64_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT64_SNAN +#define FLT64_SNAN (__builtin_nansf64 ("")) +#endif /* C23 */ +#endif /* __FLT64_MANT_DIG__. */ + +#ifdef __FLT128_MANT_DIG__ +#undef FLT128_MANT_DIG +#define FLT128_MANT_DIG __FLT128_MANT_DIG__ +#undef FLT128_DIG +#define FLT128_DIG __FLT128_DIG__ +#undef FLT128_MIN_EXP +#define FLT128_MIN_EXP __FLT128_MIN_EXP__ +#undef FLT128_MIN_10_EXP +#define FLT128_MIN_10_EXP __FLT128_MIN_10_EXP__ +#undef FLT128_MAX_EXP +#define FLT128_MAX_EXP __FLT128_MAX_EXP__ +#undef FLT128_MAX_10_EXP +#define FLT128_MAX_10_EXP __FLT128_MAX_10_EXP__ +#undef FLT128_MAX +#define FLT128_MAX __FLT128_MAX__ +#undef FLT128_EPSILON +#define FLT128_EPSILON __FLT128_EPSILON__ +#undef FLT128_MIN +#define FLT128_MIN __FLT128_MIN__ +#undef FLT128_DECIMAL_DIG +#define FLT128_DECIMAL_DIG __FLT128_DECIMAL_DIG__ +#undef FLT128_TRUE_MIN +#define FLT128_TRUE_MIN __FLT128_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT128_SNAN +#define FLT128_SNAN (__builtin_nansf128 ("")) +#endif /* C23 */ +#endif /* __FLT128_MANT_DIG__. */ + +#ifdef __FLT32X_MANT_DIG__ +#undef FLT32X_MANT_DIG +#define FLT32X_MANT_DIG __FLT32X_MANT_DIG__ +#undef FLT32X_DIG +#define FLT32X_DIG __FLT32X_DIG__ +#undef FLT32X_MIN_EXP +#define FLT32X_MIN_EXP __FLT32X_MIN_EXP__ +#undef FLT32X_MIN_10_EXP +#define FLT32X_MIN_10_EXP __FLT32X_MIN_10_EXP__ +#undef FLT32X_MAX_EXP +#define FLT32X_MAX_EXP __FLT32X_MAX_EXP__ +#undef FLT32X_MAX_10_EXP +#define FLT32X_MAX_10_EXP __FLT32X_MAX_10_EXP__ +#undef FLT32X_MAX +#define FLT32X_MAX __FLT32X_MAX__ +#undef FLT32X_EPSILON +#define FLT32X_EPSILON __FLT32X_EPSILON__ +#undef FLT32X_MIN +#define FLT32X_MIN __FLT32X_MIN__ +#undef FLT32X_DECIMAL_DIG +#define FLT32X_DECIMAL_DIG __FLT32X_DECIMAL_DIG__ +#undef FLT32X_TRUE_MIN +#define FLT32X_TRUE_MIN __FLT32X_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT32X_SNAN +#define FLT32X_SNAN (__builtin_nansf32x ("")) +#endif /* C23 */ +#endif /* __FLT32X_MANT_DIG__. */ + +#ifdef __FLT64X_MANT_DIG__ +#undef FLT64X_MANT_DIG +#define FLT64X_MANT_DIG __FLT64X_MANT_DIG__ +#undef FLT64X_DIG +#define FLT64X_DIG __FLT64X_DIG__ +#undef FLT64X_MIN_EXP +#define FLT64X_MIN_EXP __FLT64X_MIN_EXP__ +#undef FLT64X_MIN_10_EXP +#define FLT64X_MIN_10_EXP __FLT64X_MIN_10_EXP__ +#undef FLT64X_MAX_EXP +#define FLT64X_MAX_EXP __FLT64X_MAX_EXP__ +#undef FLT64X_MAX_10_EXP +#define FLT64X_MAX_10_EXP __FLT64X_MAX_10_EXP__ +#undef FLT64X_MAX +#define FLT64X_MAX __FLT64X_MAX__ +#undef FLT64X_EPSILON +#define FLT64X_EPSILON __FLT64X_EPSILON__ +#undef FLT64X_MIN +#define FLT64X_MIN __FLT64X_MIN__ +#undef FLT64X_DECIMAL_DIG +#define FLT64X_DECIMAL_DIG __FLT64X_DECIMAL_DIG__ +#undef FLT64X_TRUE_MIN +#define FLT64X_TRUE_MIN __FLT64X_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT64X_SNAN +#define FLT64X_SNAN (__builtin_nansf64x ("")) +#endif /* C23 */ +#endif /* __FLT64X_MANT_DIG__. */ + +#ifdef __FLT128X_MANT_DIG__ +#undef FLT128X_MANT_DIG +#define FLT128X_MANT_DIG __FLT128X_MANT_DIG__ +#undef FLT128X_DIG +#define FLT128X_DIG __FLT128X_DIG__ +#undef FLT128X_MIN_EXP +#define FLT128X_MIN_EXP __FLT128X_MIN_EXP__ +#undef FLT128X_MIN_10_EXP +#define FLT128X_MIN_10_EXP __FLT128X_MIN_10_EXP__ +#undef FLT128X_MAX_EXP +#define FLT128X_MAX_EXP __FLT128X_MAX_EXP__ +#undef FLT128X_MAX_10_EXP +#define FLT128X_MAX_10_EXP __FLT128X_MAX_10_EXP__ +#undef FLT128X_MAX +#define FLT128X_MAX __FLT128X_MAX__ +#undef FLT128X_EPSILON +#define FLT128X_EPSILON __FLT128X_EPSILON__ +#undef FLT128X_MIN +#define FLT128X_MIN __FLT128X_MIN__ +#undef FLT128X_DECIMAL_DIG +#define FLT128X_DECIMAL_DIG __FLT128X_DECIMAL_DIG__ +#undef FLT128X_TRUE_MIN +#define FLT128X_TRUE_MIN __FLT128X_DENORM_MIN__ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#undef FLT128X_SNAN +#define FLT128X_SNAN (__builtin_nansf128x ("")) +#endif /* C23 */ +#endif /* __FLT128X_MANT_DIG__. */ + +#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__. */ + +#ifdef __DEC32_MANT_DIG__ +#if (defined __STDC_WANT_DEC_FP__ \ + || defined __STDC_WANT_IEC_60559_DFP_EXT__ \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)) +/* C23; formerly Technical Report 24732, extension for decimal + floating-point arithmetic: Characteristic of decimal floating types + , and TS 18661-2. */ + +/* Number of base-FLT_RADIX digits in the significand, p. */ +#undef DEC32_MANT_DIG +#undef DEC64_MANT_DIG +#undef DEC128_MANT_DIG +#define DEC32_MANT_DIG __DEC32_MANT_DIG__ +#define DEC64_MANT_DIG __DEC64_MANT_DIG__ +#define DEC128_MANT_DIG __DEC128_MANT_DIG__ + +/* Minimum exponent. */ +#undef DEC32_MIN_EXP +#undef DEC64_MIN_EXP +#undef DEC128_MIN_EXP +#define DEC32_MIN_EXP __DEC32_MIN_EXP__ +#define DEC64_MIN_EXP __DEC64_MIN_EXP__ +#define DEC128_MIN_EXP __DEC128_MIN_EXP__ + +/* Maximum exponent. */ +#undef DEC32_MAX_EXP +#undef DEC64_MAX_EXP +#undef DEC128_MAX_EXP +#define DEC32_MAX_EXP __DEC32_MAX_EXP__ +#define DEC64_MAX_EXP __DEC64_MAX_EXP__ +#define DEC128_MAX_EXP __DEC128_MAX_EXP__ + +/* Maximum representable finite decimal floating-point number + (there are 6, 15, and 33 9s after the decimal points respectively). */ +#undef DEC32_MAX +#undef DEC64_MAX +#undef DEC128_MAX +#define DEC32_MAX __DEC32_MAX__ +#define DEC64_MAX __DEC64_MAX__ +#define DEC128_MAX __DEC128_MAX__ + +/* The difference between 1 and the least value greater than 1 that is + representable in the given floating point type. */ +#undef DEC32_EPSILON +#undef DEC64_EPSILON +#undef DEC128_EPSILON +#define DEC32_EPSILON __DEC32_EPSILON__ +#define DEC64_EPSILON __DEC64_EPSILON__ +#define DEC128_EPSILON __DEC128_EPSILON__ + +/* Minimum normalized positive floating-point number. */ +#undef DEC32_MIN +#undef DEC64_MIN +#undef DEC128_MIN +#define DEC32_MIN __DEC32_MIN__ +#define DEC64_MIN __DEC64_MIN__ +#define DEC128_MIN __DEC128_MIN__ + +/* The floating-point expression evaluation method. + -1 indeterminate + 0 evaluate all operations and constants just to the range and + precision of the type + 1 evaluate operations and constants of type _Decimal32 + and _Decimal64 to the range and precision of the _Decimal64 + type, evaluate _Decimal128 operations and constants to the + range and precision of the _Decimal128 type; + 2 evaluate all operations and constants to the range and + precision of the _Decimal128 type. */ + +#undef DEC_EVAL_METHOD +#define DEC_EVAL_METHOD __DEC_EVAL_METHOD__ + +#endif /* __STDC_WANT_DEC_FP__ || __STDC_WANT_IEC_60559_DFP_EXT__ || C23. */ + +#ifdef __STDC_WANT_DEC_FP__ + +/* Minimum subnormal positive floating-point number. */ +#undef DEC32_SUBNORMAL_MIN +#undef DEC64_SUBNORMAL_MIN +#undef DEC128_SUBNORMAL_MIN +#define DEC32_SUBNORMAL_MIN __DEC32_SUBNORMAL_MIN__ +#define DEC64_SUBNORMAL_MIN __DEC64_SUBNORMAL_MIN__ +#define DEC128_SUBNORMAL_MIN __DEC128_SUBNORMAL_MIN__ + +#endif /* __STDC_WANT_DEC_FP__. */ + +#if (defined __STDC_WANT_IEC_60559_DFP_EXT__ \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)) + +/* Minimum subnormal positive floating-point number. */ +#undef DEC32_TRUE_MIN +#undef DEC64_TRUE_MIN +#undef DEC128_TRUE_MIN +#define DEC32_TRUE_MIN __DEC32_SUBNORMAL_MIN__ +#define DEC64_TRUE_MIN __DEC64_SUBNORMAL_MIN__ +#define DEC128_TRUE_MIN __DEC128_SUBNORMAL_MIN__ + +#endif /* __STDC_WANT_IEC_60559_DFP_EXT__ || C23. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L + +/* Infinity in type _Decimal32. */ +#undef DEC_INFINITY +#define DEC_INFINITY (__builtin_infd32 ()) + +/* Quiet NaN in type _Decimal32. */ +#undef DEC_NAN +#define DEC_NAN (__builtin_nand32 ("")) + +/* Signaling NaN in each decimal floating-point type. */ +#undef DEC32_SNAN +#define DEC32_SNAN (__builtin_nansd32 ("")) +#undef DEC64_SNAN +#define DEC64_SNAN (__builtin_nansd64 ("")) +#undef DEC128_SNAN +#define DEC128_SNAN (__builtin_nansd128 ("")) + +#endif /* C23 */ + +#endif /* __DEC32_MANT_DIG__ */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define __STDC_VERSION_FLOAT_H__ 202311L +#endif + +#endif /* _FLOAT_H___ */ diff --git a/template/sysroot/include/fma4intrin.h b/template/sysroot/include/fma4intrin.h new file mode 100644 index 0000000..23d36b9 --- /dev/null +++ b/template/sysroot/include/fma4intrin.h @@ -0,0 +1,241 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86INTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _FMA4INTRIN_H_INCLUDED +#define _FMA4INTRIN_H_INCLUDED + +/* We need definitions from the SSE4A, SSE3, SSE2 and SSE header files. */ +#include + +#ifndef __FMA4__ +#pragma GCC push_options +#pragma GCC target("fma4") +#define __DISABLE_FMA4__ +#endif /* __FMA4__ */ + +/* 128b Floating point multiply/add type instructions. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd ((__v2df)__A, (__v2df)__B, (__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddss ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsd ((__v2df)__A, (__v2df)__B, (__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msub_ps (__m128 __A, __m128 __B, __m128 __C) + +{ + return (__m128) __builtin_ia32_vfmaddps ((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd ((__v2df)__A, (__v2df)__B, -(__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msub_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddss ((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msub_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsd ((__v2df)__A, (__v2df)__B, -(__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmacc_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddps (-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmacc_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd (-(__v2df)__A, (__v2df)__B, (__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmacc_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddss (-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmacc_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsd (-(__v2df)__A, (__v2df)__B, (__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmsub_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddps (-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmsub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddpd (-(__v2df)__A, (__v2df)__B, -(__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmsub_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddss (-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_nmsub_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsd (-(__v2df)__A, (__v2df)__B, -(__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddsub_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddsub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd ((__v2df)__A, (__v2df)__B, (__v2df)__C); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msubadd_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddsubps ((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_msubadd_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsubpd ((__v2df)__A, (__v2df)__B, -(__v2df)__C); +} + +/* 256b Floating point multiply/add type instructions. */ +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_macc_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddps256 ((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_macc_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256 ((__v4df)__A, (__v4df)__B, (__v4df)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_msub_ps (__m256 __A, __m256 __B, __m256 __C) + +{ + return (__m256) __builtin_ia32_vfmaddps256 ((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_msub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256 ((__v4df)__A, (__v4df)__B, -(__v4df)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_nmacc_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddps256 (-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_nmacc_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256 (-(__v4df)__A, (__v4df)__B, (__v4df)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_nmsub_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddps256 (-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_nmsub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddpd256 (-(__v4df)__A, (__v4df)__B, -(__v4df)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maddsub_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256 ((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maddsub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256 ((__v4df)__A, (__v4df)__B, (__v4df)__C); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_msubadd_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256) __builtin_ia32_vfmaddsubps256 ((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_msubadd_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d) __builtin_ia32_vfmaddsubpd256 ((__v4df)__A, (__v4df)__B, -(__v4df)__C); +} + +#ifdef __DISABLE_FMA4__ +#undef __DISABLE_FMA4__ +#pragma GCC pop_options +#endif /* __DISABLE_FMA4__ */ + +#endif diff --git a/template/sysroot/include/fmaintrin.h b/template/sysroot/include/fmaintrin.h new file mode 100644 index 0000000..9558378 --- /dev/null +++ b/template/sysroot/include/fmaintrin.h @@ -0,0 +1,302 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _FMAINTRIN_H_INCLUDED +#define _FMAINTRIN_H_INCLUDED + +#ifndef __FMA__ +#pragma GCC push_options +#pragma GCC target("fma") +#define __DISABLE_FMA__ +#endif /* __FMA__ */ + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfmaddpd ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmadd_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfmaddpd256 ((__v4df)__A, (__v4df)__B, + (__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfmaddps ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmadd_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfmaddps256 ((__v8sf)__A, (__v8sf)__B, + (__v8sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d) __builtin_ia32_vfmaddsd3 ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmadd_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128) __builtin_ia32_vfmaddss3 ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfmsubpd ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfmsubpd256 ((__v4df)__A, (__v4df)__B, + (__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfmsubps ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsub_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfmsubps256 ((__v8sf)__A, (__v8sf)__B, + (__v8sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfmsubsd3 ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsub_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfmsubss3 ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfnmaddpd ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmadd_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfnmaddpd256 ((__v4df)__A, (__v4df)__B, + (__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfnmaddps ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmadd_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfnmaddps256 ((__v8sf)__A, (__v8sf)__B, + (__v8sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfnmaddsd3 ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmadd_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfnmaddss3 ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfnmsubpd ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmsub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfnmsubpd256 ((__v4df)__A, (__v4df)__B, + (__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfnmsubps ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fnmsub_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfnmsubps256 ((__v8sf)__A, (__v8sf)__B, + (__v8sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_sd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfnmsubsd3 ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fnmsub_ss (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfnmsubss3 ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmaddsub_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfmaddsubpd ((__v2df)__A, (__v2df)__B, + (__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmaddsub_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfmaddsubpd256 ((__v4df)__A, + (__v4df)__B, + (__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmaddsub_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfmaddsubps ((__v4sf)__A, (__v4sf)__B, + (__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmaddsub_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfmaddsubps256 ((__v8sf)__A, + (__v8sf)__B, + (__v8sf)__C); +} + +extern __inline __m128d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsubadd_pd (__m128d __A, __m128d __B, __m128d __C) +{ + return (__m128d)__builtin_ia32_vfmaddsubpd ((__v2df)__A, (__v2df)__B, + -(__v2df)__C); +} + +extern __inline __m256d +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsubadd_pd (__m256d __A, __m256d __B, __m256d __C) +{ + return (__m256d)__builtin_ia32_vfmaddsubpd256 ((__v4df)__A, + (__v4df)__B, + -(__v4df)__C); +} + +extern __inline __m128 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_fmsubadd_ps (__m128 __A, __m128 __B, __m128 __C) +{ + return (__m128)__builtin_ia32_vfmaddsubps ((__v4sf)__A, (__v4sf)__B, + -(__v4sf)__C); +} + +extern __inline __m256 +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_fmsubadd_ps (__m256 __A, __m256 __B, __m256 __C) +{ + return (__m256)__builtin_ia32_vfmaddsubps256 ((__v8sf)__A, + (__v8sf)__B, + -(__v8sf)__C); +} + +#ifdef __DISABLE_FMA__ +#undef __DISABLE_FMA__ +#pragma GCC pop_options +#endif /* __DISABLE_FMA__ */ + +#endif diff --git a/template/sysroot/include/functional b/template/sysroot/include/functional new file mode 100644 index 0000000..9936428 --- /dev/null +++ b/template/sysroot/include/functional @@ -0,0 +1,1505 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/functional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FUNCTIONAL +#define _GLIBCXX_FUNCTIONAL 1 + +#pragma GCC system_header + +#include +#include // std::equal_to, std::unary_function etc. + +#if __cplusplus >= 201103L + +#include +#include +#include +#include +#include // std::reference_wrapper and _Mem_fn_traits +#if _GLIBCXX_HOSTED +# include // std::function +#endif +#if __cplusplus >= 201703L +# if _GLIBCXX_HOSTED +# include +# include +# include +# endif +# include // std::search +#endif +#if __cplusplus >= 202002L +# include // std::identity, ranges::equal_to etc. +# include +#endif +#if __cplusplus > 202002L && _GLIBCXX_HOSTED +# include +#endif + +#define __glibcxx_want_boyer_moore_searcher +#define __glibcxx_want_bind_front +#define __glibcxx_want_bind_back +#define __glibcxx_want_constexpr_functional +#define __glibcxx_want_invoke +#define __glibcxx_want_invoke_r +#define __glibcxx_want_move_only_function +#define __glibcxx_want_not_fn +#define __glibcxx_want_ranges +#define __glibcxx_want_reference_wrapper +#define __glibcxx_want_transparent_operators +#include + +#endif // C++11 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @brief The type of placeholder objects defined by libstdc++. + * @ingroup binders + * @since C++11 + */ + template struct _Placeholder { }; + +#ifdef __cpp_lib_invoke // C++ >= 17 + + /** Invoke a callable object. + * + * `std::invoke` takes a callable object as its first argument and calls it + * with the remaining arguments. The callable object can be a pointer or + * reference to a function, a lambda closure, a class with `operator()`, + * or even a pointer-to-member. For a pointer-to-member the first argument + * must be a reference or pointer to the object that the pointer-to-member + * will be applied to. + * + * @since C++17 + */ + template + inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...> + invoke(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_v<_Callable, _Args...>) + { + return std::__invoke(std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif + +#ifdef __cpp_lib_invoke_r // C++ >= 23 + + /** Invoke a callable object and convert the result to `_Res`. + * + * `std::invoke_r(f, args...)` is equivalent to `std::invoke(f, args...)` + * with the result implicitly converted to `R`. + * + * @since C++23 + */ + template + requires is_invocable_r_v<_Res, _Callable, _Args...> + constexpr _Res + invoke_r(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>) + { + return std::__invoke_r<_Res>(std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // __cpp_lib_invoke_r + + /// @cond undocumented + +#if __cplusplus >= 201103L + template::value> + class _Mem_fn_base + : public _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using _Traits = _Mem_fn_traits<_MemFunPtr>; + + using _Arity = typename _Traits::__arity; + using _Varargs = typename _Traits::__vararg; + + template + friend struct _Bind_check_arity; + + _MemFunPtr _M_pmf; + + public: + + using result_type = typename _Traits::__result_type; + + explicit constexpr + _Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Args&&... __args) const + noexcept(noexcept( + std::__invoke(_M_pmf, std::forward<_Args>(__args)...))) + -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...)) + { return std::__invoke(_M_pmf, std::forward<_Args>(__args)...); } + }; + + // Partial specialization for member object pointers. + template + class _Mem_fn_base<_MemObjPtr, false> + { + using _Arity = integral_constant; + using _Varargs = false_type; + + template + friend struct _Bind_check_arity; + + _MemObjPtr _M_pm; + + public: + explicit constexpr + _Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Tp&& __obj) const + noexcept(noexcept(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))) + -> decltype(std::__invoke(_M_pm, std::forward<_Tp>(__obj))) + { return std::__invoke(_M_pm, std::forward<_Tp>(__obj)); } + }; + + template + struct _Mem_fn; // undefined + + template + struct _Mem_fn<_Res _Class::*> + : _Mem_fn_base<_Res _Class::*> + { + using _Mem_fn_base<_Res _Class::*>::_Mem_fn_base; + }; + /// @endcond + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2048. Unnecessary mem_fn overloads + /** + * @brief Returns a function object that forwards to the member pointer + * pointer `pm`. + * + * This allows a pointer-to-member to be transformed into a function object + * that can be called with an object expression as its first argument. + * + * For a pointer-to-data-member the result must be called with exactly one + * argument, the object expression that would be used as the first operand + * in a `obj.*memptr` or `objp->*memptr` expression. + * + * For a pointer-to-member-function the result must be called with an object + * expression and any additional arguments to pass to the member function, + * as in an expression like `(obj.*memfun)(args...)` or + * `(objp->*memfun)(args...)`. + * + * The object expression can be a pointer, reference, `reference_wrapper`, + * or smart pointer, and the call wrapper will dereference it as needed + * to apply the pointer-to-member. + * + * @ingroup functors + * @since C++11 + */ + template + _GLIBCXX20_CONSTEXPR + inline _Mem_fn<_Tp _Class::*> + mem_fn(_Tp _Class::* __pm) noexcept + { + return _Mem_fn<_Tp _Class::*>(__pm); + } + + /** + * @brief Trait that identifies a bind expression. + * + * Determines if the given type `_Tp` is a function object that + * should be treated as a subexpression when evaluating calls to + * function objects returned by `std::bind`. + * + * C++11 [func.bind.isbind]. + * @ingroup binders + * @since C++11 + */ + template + struct is_bind_expression + : public false_type { }; + + /** + * @brief Determines if the given type _Tp is a placeholder in a + * bind() expression and, if so, which placeholder it is. + * + * C++11 [func.bind.isplace]. + * @ingroup binders + * @since C++11 + */ + template + struct is_placeholder + : public integral_constant + { }; + +#if __cplusplus > 201402L + template inline constexpr bool is_bind_expression_v + = is_bind_expression<_Tp>::value; + template inline constexpr int is_placeholder_v + = is_placeholder<_Tp>::value; +#endif // C++17 + + /** @namespace std::placeholders + * @brief ISO C++ 2011 namespace for std::bind placeholders. + * @ingroup binders + * @since C++11 + */ + namespace placeholders + { + /* Define a large number of placeholders. There is no way to + * simplify this with variadic templates, because we're introducing + * unique names for each. + */ +#if __cpp_inline_variables +# define _GLIBCXX_PLACEHOLDER inline +#else +# define _GLIBCXX_PLACEHOLDER extern +#endif + + _GLIBCXX_PLACEHOLDER const _Placeholder<1> _1; + _GLIBCXX_PLACEHOLDER const _Placeholder<2> _2; + _GLIBCXX_PLACEHOLDER const _Placeholder<3> _3; + _GLIBCXX_PLACEHOLDER const _Placeholder<4> _4; + _GLIBCXX_PLACEHOLDER const _Placeholder<5> _5; + _GLIBCXX_PLACEHOLDER const _Placeholder<6> _6; + _GLIBCXX_PLACEHOLDER const _Placeholder<7> _7; + _GLIBCXX_PLACEHOLDER const _Placeholder<8> _8; + _GLIBCXX_PLACEHOLDER const _Placeholder<9> _9; + _GLIBCXX_PLACEHOLDER const _Placeholder<10> _10; + _GLIBCXX_PLACEHOLDER const _Placeholder<11> _11; + _GLIBCXX_PLACEHOLDER const _Placeholder<12> _12; + _GLIBCXX_PLACEHOLDER const _Placeholder<13> _13; + _GLIBCXX_PLACEHOLDER const _Placeholder<14> _14; + _GLIBCXX_PLACEHOLDER const _Placeholder<15> _15; + _GLIBCXX_PLACEHOLDER const _Placeholder<16> _16; + _GLIBCXX_PLACEHOLDER const _Placeholder<17> _17; + _GLIBCXX_PLACEHOLDER const _Placeholder<18> _18; + _GLIBCXX_PLACEHOLDER const _Placeholder<19> _19; + _GLIBCXX_PLACEHOLDER const _Placeholder<20> _20; + _GLIBCXX_PLACEHOLDER const _Placeholder<21> _21; + _GLIBCXX_PLACEHOLDER const _Placeholder<22> _22; + _GLIBCXX_PLACEHOLDER const _Placeholder<23> _23; + _GLIBCXX_PLACEHOLDER const _Placeholder<24> _24; + _GLIBCXX_PLACEHOLDER const _Placeholder<25> _25; + _GLIBCXX_PLACEHOLDER const _Placeholder<26> _26; + _GLIBCXX_PLACEHOLDER const _Placeholder<27> _27; + _GLIBCXX_PLACEHOLDER const _Placeholder<28> _28; + _GLIBCXX_PLACEHOLDER const _Placeholder<29> _29; + +#undef _GLIBCXX_PLACEHOLDER + } + + /** + * Partial specialization of is_placeholder that provides the placeholder + * number for the placeholder objects defined by libstdc++. + * @ingroup binders + * @since C++11 + */ + template + struct is_placeholder<_Placeholder<_Num> > + : public integral_constant + { }; + + template + struct is_placeholder > + : public integral_constant + { }; + + /// @cond undocumented + + // Like tuple_element_t but SFINAE-friendly. + template + using _Safe_tuple_element_t + = typename enable_if<(__i < tuple_size<_Tuple>::value), + tuple_element<__i, _Tuple>>::type::type; + + /** + * Maps an argument to bind() into an actual argument to the bound + * function object [func.bind.bind]/10. Only the first parameter should + * be specified: the rest are used to determine among the various + * implementations. Note that, although this class is a function + * object, it isn't entirely normal because it takes only two + * parameters regardless of the number of parameters passed to the + * bind expression. The first parameter is the bound argument and + * the second parameter is a tuple containing references to the + * rest of the arguments. + */ + template::value, + bool _IsPlaceholder = (is_placeholder<_Arg>::value > 0)> + class _Mu; + + /** + * If the argument is reference_wrapper<_Tp>, returns the + * underlying reference. + * C++11 [func.bind.bind] p10 bullet 1. + */ + template + class _Mu, false, false> + { + public: + /* Note: This won't actually work for const volatile + * reference_wrappers, because reference_wrapper::get() is const + * but not volatile-qualified. This might be a defect in the TR. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp& + operator()(_CVRef& __arg, _Tuple&) const volatile + { return __arg.get(); } + }; + + /** + * If the argument is a bind expression, we invoke the underlying + * function object with the same cv-qualifiers as we are given and + * pass along all of our arguments (unwrapped). + * C++11 [func.bind.bind] p10 bullet 2. + */ + template + class _Mu<_Arg, true, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_CVArg& __arg, + tuple<_Args...>& __tuple) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + // Construct an index tuple and forward to __call + typedef typename _Build_index_tuple::__type + _Indexes; + return this->__call(__arg, __tuple, _Indexes()); + } + + private: + // Invokes the underlying function object __arg by unpacking all + // of the arguments in the tuple. + template + _GLIBCXX20_CONSTEXPR + auto + __call(_CVArg& __arg, tuple<_Args...>& __tuple, + const _Index_tuple<_Indexes...>&) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + return __arg(std::get<_Indexes>(std::move(__tuple))...); + } + }; + + /** + * If the argument is a placeholder for the Nth argument, returns + * a reference to the Nth argument to the bind function object. + * C++11 [func.bind.bind] p10 bullet 3. + */ + template + class _Mu<_Arg, false, true> + { + public: + template + _GLIBCXX20_CONSTEXPR + _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& + operator()(const volatile _Arg&, _Tuple& __tuple) const volatile + { + return + ::std::get<(is_placeholder<_Arg>::value - 1)>(std::move(__tuple)); + } + }; + + /** + * If the argument is just a value, returns a reference to that + * value. The cv-qualifiers on the reference are determined by the caller. + * C++11 [func.bind.bind] p10 bullet 4. + */ + template + class _Mu<_Arg, false, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + _CVArg&& + operator()(_CVArg&& __arg, _Tuple&) const volatile + { return std::forward<_CVArg>(__arg); } + }; + + // std::get for volatile-qualified tuples + template + inline auto + __volget(volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + // std::get for const-volatile-qualified tuples + template + inline auto + __volget(const volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> const volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + /// @endcond + +#if __cplusplus == 201703L && _GLIBCXX_USE_DEPRECATED +# define _GLIBCXX_VOLATILE_BIND +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 2487. bind() should be const-overloaded, not cv-overloaded +# define _GLIBCXX_DEPR_BIND \ + [[deprecated("std::bind does not support volatile in C++17")]] +#elif __cplusplus < 201703L +# define _GLIBCXX_VOLATILE_BIND +# define _GLIBCXX_DEPR_BIND +#endif + + /// Type of the function object returned from bind(). + template + class _Bind; + + template + class _Bind<_Functor(_Bound_args...)> + : public _Weak_result_type<_Functor> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Result + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Result + __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + +#ifdef _GLIBCXX_VOLATILE_BIND + // Call as volatile + template + _Result + __call_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const volatile + template + _Result + __call_c_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } +#endif // volatile + + template + using _Mu_type = decltype( + _Mu::type>()( + std::declval<_BoundArg&>(), std::declval<_CallArgs&>()) ); + + template + using _Res_type_impl + = __invoke_result_t<_Fn&, _Mu_type<_BArgs, _CallArgs>&&...>; + + template + using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; + + template + using __dependent = typename + enable_if::value+1), _Functor>::type; + + template class __cv_quals> + using _Res_type_cv = _Res_type_impl< + typename __cv_quals<__dependent<_CallArgs>>::type, + _CallArgs, + typename __cv_quals<_Bound_args>::type...>; + + public: + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind(const _Bind&) = default; + _Bind(_Bind&&) = default; + + // Call unqualified + template>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template, add_const>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) const + { + return this->__call_c<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + +#ifdef _GLIBCXX_VOLATILE_BIND + // Call as volatile + template, add_volatile>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) volatile + { + return this->__call_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template, add_cv>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) const volatile + { + return this->__call_c_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } +#endif // volatile + }; + + /// Type of the function object returned from bind(). + template + class _Bind_result; + + template + class _Bind_result<_Result, _Functor(_Bound_args...)> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + +#ifdef _GLIBCXX_VOLATILE_BIND + // Call as volatile + template + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const volatile + template + _Res + __call(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } +#endif // volatile + + public: + typedef _Result result_type; + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind_result(const _Bind_result&) = default; + _Bind_result(_Bind_result&&) = default; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) const + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + +#ifdef _GLIBCXX_VOLATILE_BIND + // Call as volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) const volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } +#else + template + void operator()(_Args&&...) const volatile = delete; +#endif // volatile + }; + +#undef _GLIBCXX_VOLATILE_BIND +#undef _GLIBCXX_DEPR_BIND + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind<_Signature> > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + template + struct _Bind_check_arity { }; + + template + struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) == sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...> + { + using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity; + using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs; + static_assert(_Varargs::value + ? sizeof...(_BoundArgs) >= _Arity::value + 1 + : sizeof...(_BoundArgs) == _Arity::value + 1, + "Wrong number of arguments for pointer-to-member"); + }; + + // Trait type used to remove std::bind() from overload set via SFINAE + // when first argument has integer type, so that std::bind() will + // not be a better match than ::bind() from the BSD Sockets API. + template::type> + using __is_socketlike = __or_, is_enum<_Tp2>>; + + template + struct _Bind_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __func_type; + typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type; + }; + + // Partial specialization for is_socketlike == true, does not define + // nested type so std::bind() will not participate in overload resolution + // when the first argument might be a socket file descriptor. + template + struct _Bind_helper + { }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + * @since C++11 + */ + template + inline _GLIBCXX20_CONSTEXPR typename + _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bind_helper __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + + template + struct _Bindres_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __functor_type; + typedef _Bind_result<_Result, + __functor_type(typename decay<_BoundArgs>::type...)> + type; + }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + * @since C++11 + */ + template + inline _GLIBCXX20_CONSTEXPR + typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + +#ifdef __cpp_lib_bind_front // C++ >= 20 + + template + struct _Bind_front + { + static_assert(is_move_constructible_v<_Fd>); + static_assert((is_move_constructible_v<_BoundArgs> && ...)); + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template + explicit constexpr + _Bind_front(int, _Fn&& __fn, _Args&&... __args) + noexcept(__and_, + is_nothrow_constructible<_BoundArgs, _Args>...>::value) + : _M_fd(std::forward<_Fn>(__fn)), + _M_bound_args(std::forward<_Args>(__args)...) + { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } + +#if __cpp_explicit_this_parameter + template + constexpr + invoke_result_t<__like_t<_Self, _Fd>, __like_t<_Self, _BoundArgs>..., _CallArgs...> + operator()(this _Self&& __self, _CallArgs&&... __call_args) + noexcept(is_nothrow_invocable_v<__like_t<_Self, _Fd>, + __like_t<_Self, _BoundArgs>..., _CallArgs...>) + { + return _S_call(std::forward<_Self>(__self), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } +#else + template + requires true + constexpr + invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...> + operator()(_CallArgs&&... __call_args) & + noexcept(is_nothrow_invocable_v<_Fd&, _BoundArgs&..., _CallArgs...>) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + requires true + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const & + noexcept(is_nothrow_invocable_v) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + requires true + constexpr + invoke_result_t<_Fd, _BoundArgs..., _CallArgs...> + operator()(_CallArgs&&... __call_args) && + noexcept(is_nothrow_invocable_v<_Fd, _BoundArgs..., _CallArgs...>) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + requires true + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const && + noexcept(is_nothrow_invocable_v) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + void operator()(_CallArgs&&...) & = delete; + + template + void operator()(_CallArgs&&...) const & = delete; + + template + void operator()(_CallArgs&&...) && = delete; + + template + void operator()(_CallArgs&&...) const && = delete; +#endif + + private: + using _BoundIndices = index_sequence_for<_BoundArgs...>; + + template + static constexpr + decltype(auto) + _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args) + { + return std::invoke(std::forward<_Tp>(__g)._M_fd, + std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)..., + std::forward<_CallArgs>(__call_args)...); + } + + [[no_unique_address]] _Fd _M_fd; + [[no_unique_address]] std::tuple<_BoundArgs...> _M_bound_args; + }; + + template + using _Bind_front_t = _Bind_front, decay_t<_Args>...>; + + /** Create call wrapper by partial application of arguments to function. + * + * The result of `std::bind_front(f, args...)` is a function object that + * stores `f` and the bound arguments, `args...`. When that function + * object is invoked with `call_args...` it returns the result of calling + * `f(args..., call_args...)`. + * + * @since C++20 + */ + template + constexpr _Bind_front_t<_Fn, _Args...> + bind_front(_Fn&& __fn, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Bind_front_t<_Fn, _Args...>, + int, _Fn, _Args...>) + { + return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn), + std::forward<_Args>(__args)...); + } +#endif // __cpp_lib_bind_front + +#ifdef __cpp_lib_bind_back // C++ >= 23 + template + struct _Bind_back + { + static_assert(is_move_constructible_v<_Fd>); + static_assert((is_move_constructible_v<_BoundArgs> && ...)); + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template + explicit constexpr + _Bind_back(int, _Fn&& __fn, _Args&&... __args) + noexcept(__and_, + is_nothrow_constructible<_BoundArgs, _Args>...>::value) + : _M_fd(std::forward<_Fn>(__fn)), + _M_bound_args(std::forward<_Args>(__args)...) + { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } + + template + constexpr + invoke_result_t<__like_t<_Self, _Fd>, _CallArgs..., __like_t<_Self, _BoundArgs>...> + operator()(this _Self&& __self, _CallArgs&&... __call_args) + noexcept(is_nothrow_invocable_v<__like_t<_Self, _Fd>, + _CallArgs..., __like_t<_Self, _BoundArgs>...>) + { + return _S_call(std::forward<_Self>(__self), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + private: + using _BoundIndices = index_sequence_for<_BoundArgs...>; + + template + static constexpr + decltype(auto) + _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args) + { + return std::invoke(std::forward<_Tp>(__g)._M_fd, + std::forward<_CallArgs>(__call_args)..., + std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)...); + } + + [[no_unique_address]] _Fd _M_fd; + [[no_unique_address]] std::tuple<_BoundArgs...> _M_bound_args; + }; + + template + using _Bind_back_t = _Bind_back, decay_t<_Args>...>; + + /** Create call wrapper by partial application of arguments to function. + * + * The result of `std::bind_back(f, args...)` is a function object that + * stores `f` and the bound arguments, `args...`. When that function + * object is invoked with `call_args...` it returns the result of calling + * `f(call_args..., args...)`. + * + * @since C++23 + */ + template + constexpr _Bind_back_t<_Fn, _Args...> + bind_back(_Fn&& __fn, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Bind_back_t<_Fn, _Args...>, + int, _Fn, _Args...>) + { + return _Bind_back_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn), + std::forward<_Args>(__args)...); + } +#endif // __cpp_lib_bind_back + +#if __cplusplus >= 201402L + /// Generalized negator. + template + class _Not_fn + { + template + using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type; + + template + static decltype(!std::declval<_Tp>()) + _S_not() noexcept(noexcept(!std::declval<_Tp>())); + + public: + template + constexpr + _Not_fn(_Fn2&& __fn, int) + : _M_fn(std::forward<_Fn2>(__fn)) { } + + _Not_fn(const _Not_fn& __fn) = default; + _Not_fn(_Not_fn&& __fn) = default; + ~_Not_fn() = default; + + // Macro to define operator() with given cv-qualifiers ref-qualifiers, + // forwarding _M_fn and the function arguments with the same qualifiers, + // and deducing the return type and exception-specification. +#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ + template::value>> \ + _GLIBCXX20_CONSTEXPR \ + decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ + operator()(_Args&&... __args) _QUALS \ + noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value \ + && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) \ + { \ + return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \ + std::forward<_Args>(__args)...); \ + } \ + \ + template::value>> \ + void operator()(_Args&&... __args) _QUALS = delete; + + _GLIBCXX_NOT_FN_CALL_OP( & ) + _GLIBCXX_NOT_FN_CALL_OP( const & ) + _GLIBCXX_NOT_FN_CALL_OP( && ) + _GLIBCXX_NOT_FN_CALL_OP( const && ) +#undef _GLIBCXX_NOT_FN_CALL_OP + + private: + _Fn _M_fn; + }; + + template + struct __is_byte_like : false_type { }; + + template + struct __is_byte_like<_Tp, equal_to<_Tp>> + : __bool_constant::value> { }; + + template + struct __is_byte_like<_Tp, equal_to> + : __bool_constant::value> { }; + +#if __cplusplus >= 201703L + // Declare std::byte (full definition is in ). + enum class byte : unsigned char; + + template<> + struct __is_byte_like> + : true_type { }; + + template<> + struct __is_byte_like> + : true_type { }; +#endif + + // [func.not_fn] Function template not_fn +#ifdef __cpp_lib_not_fn // C++ >= 17 + /** Wrap a function object to create one that negates its result. + * + * The function template `std::not_fn` creates a "forwarding call wrapper", + * which is a function object that wraps another function object and + * when called, forwards its arguments to the wrapped function object. + * + * The result of invoking the wrapper is the negation (using `!`) of + * the wrapped function object. + * + * @ingroup functors + * @since C++17 + */ + template + _GLIBCXX20_CONSTEXPR + inline auto + not_fn(_Fn&& __fn) + noexcept(std::is_nothrow_constructible, _Fn&&>::value) + { + return _Not_fn>{std::forward<_Fn>(__fn), 0}; + } +#endif + +#if __cplusplus >= 201703L + // Searchers + + template> + class default_searcher + { + public: + _GLIBCXX20_CONSTEXPR + default_searcher(_ForwardIterator1 __pat_first, + _ForwardIterator1 __pat_last, + _BinaryPredicate __pred = _BinaryPredicate()) + : _M_m(__pat_first, __pat_last, std::move(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator2, _ForwardIterator2> + operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const + { + _ForwardIterator2 __first_ret = + std::search(__first, __last, std::get<0>(_M_m), std::get<1>(_M_m), + std::get<2>(_M_m)); + auto __ret = std::make_pair(__first_ret, __first_ret); + if (__ret.first != __last) + std::advance(__ret.second, std::distance(std::get<0>(_M_m), + std::get<1>(_M_m))); + return __ret; + } + + private: + tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m; + }; + +#ifdef __cpp_lib_boyer_moore_searcher // C++ >= 17 && HOSTED + + template + struct __boyer_moore_map_base + { + template + __boyer_moore_map_base(_RAIter __pat, size_t __patlen, + _Hash&& __hf, _Pred&& __pred) + : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) } + { + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + _M_bad_char[__pat[__i]] = __patlen - 1 - __i; + } + + using __diff_type = _Tp; + + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __iter = _M_bad_char.find(__key); + if (__iter == _M_bad_char.end()) + return __not_found; + return __iter->second; + } + + _Pred + _M_pred() const { return _M_bad_char.key_eq(); } + + _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char; + }; + + template + struct __boyer_moore_array_base + { + template + __boyer_moore_array_base(_RAIter __pat, size_t __patlen, + _Unused&&, _Pred&& __pred) + : _M_bad_char{ array<_Tp, _Len>{}, std::move(__pred) } + { + std::get<0>(_M_bad_char).fill(__patlen); + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + { + auto __ch = __pat[__i]; + using _UCh = make_unsigned_t; + auto __uch = static_cast<_UCh>(__ch); + std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i; + } + } + + using __diff_type = _Tp; + + template + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __ukey = static_cast>(__key); + if (__ukey >= _Len) + return __not_found; + return std::get<0>(_M_bad_char)[__ukey]; + } + + const _Pred& + _M_pred() const { return std::get<1>(_M_bad_char); } + + tuple, _Pred> _M_bad_char; + }; + + // Use __boyer_moore_array_base when pattern consists of narrow characters + // (or std::byte) and uses std::equal_to as the predicate. + template::value_type, + typename _Diff = typename iterator_traits<_RAIter>::difference_type> + using __boyer_moore_base_t + = __conditional_t<__is_byte_like<_Val, _Pred>::value, + __boyer_moore_array_base<_Diff, 256, _Pred>, + __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last, + _Hash __hf = _Hash(), + _BinaryPredicate __pred = _BinaryPredicate()); + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const; + + private: + bool + _M_is_prefix(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __suffixlen = __len - __pos; + for (__diff_type __i = 0; __i < __suffixlen; ++__i) + if (!__pred(__word[__i], __word[__pos + __i])) + return false; + return true; + } + + __diff_type + _M_suffix_length(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __i = 0; + while (__pred(__word[__pos - __i], __word[__len - 1 - __i]) + && __i < __pos) + { + ++__i; + } + return __i; + } + + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + _GLIBCXX_STD_C::vector<__diff_type> _M_good_suffix; + }; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_horspool_searcher(_RAIter __pat, + _RAIter __pat_end, + _Hash __hf = _Hash(), + _BinaryPredicate __pred + = _BinaryPredicate()) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end) + { } + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + const auto& __pred = this->_M_pred(); + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + auto __len = __last - __first; + while (__len >= __patlen) + { + for (auto __scan = __patlen - 1; + __pred(__first[__scan], _M_pat[__scan]); --__scan) + if (__scan == 0) + return std::make_pair(__first, __first + __patlen); + auto __shift = _M_bad_char_shift(__first[__patlen - 1]); + __len -= __shift; + __first += __shift; + } + return std::make_pair(__last, __last); + } + + private: + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + }; + + template + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end, + _Hash __hf, _BinaryPredicate __pred) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat) + { + auto __patlen = __pat_end - __pat; + if (__patlen == 0) + return; + __diff_type __last_prefix = __patlen - 1; + for (__diff_type __p = __patlen - 1; __p >= 0; --__p) + { + if (_M_is_prefix(__pat, __patlen, __p + 1)) + __last_prefix = __p + 1; + _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p); + } + for (__diff_type __p = 0; __p < __patlen - 1; ++__p) + { + auto __slen = _M_suffix_length(__pat, __patlen, __p); + auto __pos = __patlen - 1 - __slen; + if (!__pred(__pat[__p - __slen], __pat[__pos])) + _M_good_suffix[__pos] = __patlen - 1 - __p + __slen; + } + } + + template + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + const auto& __pred = this->_M_pred(); + __diff_type __i = __patlen - 1; + auto __stringlen = __last - __first; + while (__i < __stringlen) + { + __diff_type __j = __patlen - 1; + while (__j >= 0 && __pred(__first[__i], _M_pat[__j])) + { + --__i; + --__j; + } + if (__j < 0) + { + const auto __match = __first + __i + 1; + return std::make_pair(__match, __match + __patlen); + } + __i += std::max(_M_bad_char_shift(__first[__i]), + _M_good_suffix[__j]); + } + return std::make_pair(__last, __last); + } +#endif // __cpp_lib_boyer_moore_searcher + +#endif // C++17 +#endif // C++14 +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _GLIBCXX_FUNCTIONAL diff --git a/template/sysroot/include/fxsrintrin.h b/template/sysroot/include/fxsrintrin.h new file mode 100644 index 0000000..8661e0f --- /dev/null +++ b/template/sysroot/include/fxsrintrin.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _FXSRINTRIN_H_INCLUDED +#define _FXSRINTRIN_H_INCLUDED + +#ifndef __FXSR__ +#pragma GCC push_options +#pragma GCC target("fxsr") +#define __DISABLE_FXSR__ +#endif /* __FXSR__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxsave (void *__P) +{ + __builtin_ia32_fxsave (__P); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxrstor (void *__P) +{ + __builtin_ia32_fxrstor (__P); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxsave64 (void *__P) +{ + __builtin_ia32_fxsave64 (__P); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxrstor64 (void *__P) +{ + __builtin_ia32_fxrstor64 (__P); +} +#endif + +#ifdef __DISABLE_FXSR__ +#undef __DISABLE_FXSR__ +#pragma GCC pop_options +#endif /* __DISABLE_FXSR__ */ + + +#endif /* _FXSRINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/gcov.h b/template/sysroot/include/gcov.h new file mode 100644 index 0000000..8ec4937 --- /dev/null +++ b/template/sysroot/include/gcov.h @@ -0,0 +1,70 @@ +/* GCOV interface routines. + Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef GCC_GCOV_H +#define GCC_GCOV_H + +struct gcov_info; + +/* Set all counters to zero. */ + +extern void __gcov_reset (void); + +/* Write profile information to a file. */ + +extern void __gcov_dump (void); + +/* Convert the gcov information referenced by INFO to a gcda data stream. + The FILENAME_FN callback is called exactly once with the filename associated + with the gcov information. The filename may be NULL. Afterwards, the + DUMP_FN callback is subsequently called with chunks (the begin and length of + the chunk are passed as the first two callback parameters) of the gcda data + stream. The ALLOCATE_FN callback shall allocate memory with a size in + characters specified by the first callback parameter. The ARG parameter is + a user-provided argument passed as the last argument to the callback + functions. It is recommended to use the __gcov_filename_to_gcfn() + in the filename callback function. */ + +extern void +__gcov_info_to_gcda (const struct gcov_info *__info, + void (*__filename_fn) (const char *, void *), + void (*__dump_fn) (const void *, unsigned, void *), + void *(*__allocate_fn) (unsigned, void *), + void *__arg); + +/* Convert the FILENAME to a gcfn data stream. The DUMP_FN callback is + subsequently called with chunks (the begin and length of the chunk are + passed as the first two callback parameters) of the gcfn data stream. + The ARG parameter is a user-provided argument passed as the last + argument to the DUMP_FN callback function. This function is intended + to be used by the filename callback of __gcov_info_to_gcda(). The gcfn + data stream is used by the merge-stream subcommand of the gcov-tool to + get the filename associated with a gcda data stream. */ + +extern void +__gcov_filename_to_gcfn (const char *__filename, + void (*__dump_fn) (const void *, unsigned, void *), + void *__arg); + +#endif /* GCC_GCOV_H */ diff --git a/template/sysroot/include/generator b/template/sysroot/include/generator new file mode 100644 index 0000000..1d5acc9 --- /dev/null +++ b/template/sysroot/include/generator @@ -0,0 +1,821 @@ +// -*- C++ -*- + +// Copyright (C) 2023-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/generator + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_GENERATOR +#define _GLIBCXX_GENERATOR + +#include +#pragma GCC system_header + +#include + +#define __glibcxx_want_generator +#include + +#ifdef __cpp_lib_generator // C++ >= 23 && __glibcxx_coroutine +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if _GLIBCXX_HOSTED +# include +#endif // HOSTED + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup generator_coros Range generator coroutines + * @addtogroup ranges + * @since C++23 + * @{ + */ + + /** @brief A range specified using a yielding coroutine. + * + * `std::generator` is a utility class for defining ranges using coroutines + * that yield elements as a range. Generator coroutines are synchronous. + * + * @headerfile generator + * @since C++23 + */ + template + class generator; + + /// @cond undocumented + namespace __gen + { + /// _Reference type for a generator whose reference (first argument) and + /// value (second argument) types are _Ref and _Val. + template + using _Reference_t = __conditional_t, + _Ref&&, _Ref>; + + /// Type yielded by a generator whose _Reference type is _Reference. + template + using _Yield_t = __conditional_t, + _Reference, + const _Reference&>; + + /// _Yield_t * _Reference_t + template + using _Yield2_t = _Yield_t<_Reference_t<_Ref, _Val>>; + + template constexpr bool __is_generator = false; + template + constexpr bool __is_generator> = true; + + /// Allocator and value type erased generator promise type. + /// \tparam _Yielded The corresponding generators yielded type. + template + class _Promise_erased + { + static_assert(is_reference_v<_Yielded>); + using _Yielded_deref = remove_reference_t<_Yielded>; + using _Yielded_decvref = remove_cvref_t<_Yielded>; + using _ValuePtr = add_pointer_t<_Yielded>; + using _Coro_handle = std::coroutine_handle<_Promise_erased>; + + template + friend class std::generator; + + template + struct _Recursive_awaiter; + template + friend struct _Recursive_awaiter; + struct _Copy_awaiter; + struct _Subyield_state; + struct _Final_awaiter; + public: + suspend_always + initial_suspend() const noexcept + { return {}; } + + suspend_always + yield_value(_Yielded __val) noexcept + { + _M_bottom_value() = ::std::addressof(__val); + return {}; + } + + auto + yield_value(const _Yielded_deref& __val) + noexcept (is_nothrow_constructible_v<_Yielded_decvref, + const _Yielded_deref&>) + requires (is_rvalue_reference_v<_Yielded> + && constructible_from<_Yielded_decvref, + const _Yielded_deref&>) + { return _Copy_awaiter(__val, _M_bottom_value()); } + + template + requires std::same_as<_Yield2_t<_R2, _V2>, _Yielded> + auto + yield_value(ranges::elements_of&&, _U2> __r) + noexcept + { return _Recursive_awaiter { std::move(__r.range) }; } + + template + requires convertible_to, _Yielded> + auto + yield_value(ranges::elements_of<_R, _Alloc> __r) + { + auto __n = [] (allocator_arg_t, _Alloc, + ranges::iterator_t<_R> __i, + ranges::sentinel_t<_R> __s) + -> generator<_Yielded, ranges::range_value_t<_R>, _Alloc> { + for (; __i != __s; ++__i) + co_yield static_cast<_Yielded>(*__i); + }; + return yield_value(ranges::elements_of(__n(allocator_arg, + __r.allocator, + ranges::begin(__r.range), + ranges::end(__r.range)))); + } + + + _Final_awaiter + final_suspend() noexcept + { return {}; } + + void + unhandled_exception() + { + // To get to this point, this coroutine must have been active. In that + // case, it must be the top of the stack. The current coroutine is + // the sole entry of the stack iff it is both the top and the bottom. As + // it is the top implicitly in this context it will be the sole entry iff + // it is the bottom. + if (_M_nest._M_is_bottom()) + throw; + else + this->_M_except = std::current_exception(); + } + + void await_transform() = delete; + void return_void() const noexcept {} + + private: + _ValuePtr& + _M_bottom_value() noexcept + { return _M_nest._M_bottom_value(*this); } + + _ValuePtr& + _M_value() noexcept + { return _M_nest._M_value(*this); } + + _Subyield_state _M_nest; + std::exception_ptr _M_except; + }; + + template + struct _Promise_erased<_Yielded>::_Subyield_state + { + struct _Frame + { + _Coro_handle _M_bottom; + _Coro_handle _M_parent; + }; + + struct _Bottom_frame + { + _Coro_handle _M_top; + _ValuePtr _M_value = nullptr; + }; + + std::variant< + _Bottom_frame, + _Frame + > _M_stack; + + bool + _M_is_bottom() const noexcept + { return !std::holds_alternative<_Frame>(this->_M_stack); } + + _Coro_handle& + _M_top() noexcept + { + if (auto __f = std::get_if<_Frame>(&this->_M_stack)) + return __f->_M_bottom.promise()._M_nest._M_top(); + + auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack); + __glibcxx_assert(__bf); + return __bf->_M_top; + } + + void + _M_push(_Coro_handle __current, _Coro_handle __subyield) noexcept + { + __glibcxx_assert(&__current.promise()._M_nest == this); + __glibcxx_assert(this->_M_top() == __current); + + __subyield.promise()._M_nest._M_jump_in(__current, __subyield); + } + + std::coroutine_handle<> + _M_pop() noexcept + { + if (auto __f = std::get_if<_Frame>(&this->_M_stack)) + { + // We aren't a bottom coroutine. Restore the parent to the top + // and resume. + auto __p = this->_M_top() = __f->_M_parent; + return __p; + } + else + // Otherwise, there's nothing to resume. + return std::noop_coroutine(); + } + + void + _M_jump_in(_Coro_handle __rest, _Coro_handle __new) noexcept + { + __glibcxx_assert(&__new.promise()._M_nest == this); + __glibcxx_assert(this->_M_is_bottom()); + // We're bottom. We're also top if top is unset (note that this is + // not true if something was added to the coro stack and then popped, + // but in that case we can't possibly be yielded from, as it would + // require rerunning begin()). + __glibcxx_assert(!this->_M_top()); + + auto& __rn = __rest.promise()._M_nest; + __rn._M_top() = __new; + + // Presume we're the second frame... + auto __bott = __rest; + if (auto __f = std::get_if<_Frame>(&__rn._M_stack)) + // But, if we aren't, get the actual bottom. We're only the second + // frame if our parent is the bottom frame, i.e. it doesn't have a + // _Frame member. + __bott = __f->_M_bottom; + + this->_M_stack = _Frame { + ._M_bottom = __bott, + ._M_parent = __rest + }; + } + + _ValuePtr& + _M_bottom_value(_Promise_erased& __current) noexcept + { + __glibcxx_assert(&__current._M_nest == this); + if (auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack)) + return __bf->_M_value; + auto __f = std::get_if<_Frame>(&this->_M_stack); + __glibcxx_assert(__f); + auto& __p = __f->_M_bottom.promise(); + return __p._M_nest._M_value(__p); + } + + _ValuePtr& + _M_value(_Promise_erased& __current) noexcept + { + __glibcxx_assert(&__current._M_nest == this); + auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack); + __glibcxx_assert(__bf); + return __bf->_M_value; + } + }; + + template + struct _Promise_erased<_Yielded>::_Final_awaiter + { + bool await_ready() noexcept + { return false; } + + template + auto await_suspend(std::coroutine_handle<_Promise> __c) noexcept + { +#ifdef __glibcxx_is_pointer_interconvertible + static_assert(is_pointer_interconvertible_base_of_v< + _Promise_erased, _Promise>); +#endif + + auto& __n = __c.promise()._M_nest; + return __n._M_pop(); + } + + void await_resume() noexcept {} + }; + + template + struct _Promise_erased<_Yielded>::_Copy_awaiter + { + _Yielded_decvref _M_value; + _ValuePtr& _M_bottom_value; + + constexpr bool await_ready() noexcept + { return false; } + + template + void await_suspend(std::coroutine_handle<_Promise>) noexcept + { +#ifdef __glibcxx_is_pointer_interconvertible + static_assert(is_pointer_interconvertible_base_of_v< + _Promise_erased, _Promise>); +#endif + _M_bottom_value = ::std::addressof(_M_value); + } + + constexpr void + await_resume() const noexcept + {} + }; + + template + template + struct _Promise_erased<_Yielded>::_Recursive_awaiter + { + _Gen _M_gen; + static_assert(__is_generator<_Gen>); + static_assert(std::same_as); + + _Recursive_awaiter(_Gen __gen) noexcept + : _M_gen(std::move(__gen)) + { this->_M_gen._M_mark_as_started(); } + + constexpr bool + await_ready() const noexcept + { return false; } + + + template + std::coroutine_handle<> + await_suspend(std::coroutine_handle<_Promise> __p) noexcept + { +#ifdef __glibcxx_is_pointer_interconvertible + static_assert(is_pointer_interconvertible_base_of_v< + _Promise_erased, _Promise>); +#endif + + auto __c = _Coro_handle::from_address(__p.address()); + auto __t = _Coro_handle::from_address(this->_M_gen._M_coro.address()); + __p.promise()._M_nest._M_push(__c, __t); + return __t; + } + + void await_resume() + { + if (auto __e = _M_gen._M_coro.promise()._M_except) + std::rethrow_exception(__e); + } + }; + + struct _Alloc_block + { + alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) + char _M_data[__STDCPP_DEFAULT_NEW_ALIGNMENT__]; + + static auto + _M_cnt(std::size_t __sz) noexcept + { + auto __blksz = sizeof(_Alloc_block); + return (__sz + __blksz - 1) / __blksz; + } + }; + + template + concept _Stateless_alloc = (allocator_traits<_All>::is_always_equal::value + && default_initializable<_All>); + + template + class _Promise_alloc + { + using _ATr = allocator_traits<_Alloc>; + using _Rebound = typename _ATr::template rebind_alloc<_Alloc_block>; + using _Rebound_ATr = typename _ATr + ::template rebind_traits<_Alloc_block>; + static_assert(is_pointer_v, + "Must use allocators for true pointers with generators"); + + static auto + _M_alloc_address(std::uintptr_t __fn, std::uintptr_t __fsz) noexcept + { + auto __an = __fn + __fsz; + auto __ba = alignof(_Rebound); + return reinterpret_cast<_Rebound*>(((__an + __ba - 1) / __ba) * __ba); + } + + static auto + _M_alloc_size(std::size_t __csz) noexcept + { + auto __ba = alignof(_Rebound); + // Our desired layout is placing the coroutine frame, then pad out to + // align, then place the allocator. The total size of that is the + // size of the coroutine frame, plus up to __ba bytes, plus the size + // of the allocator. + return __csz + __ba + sizeof(_Rebound); + } + + static void* + _M_allocate(_Rebound __b, std::size_t __csz) + { + if constexpr (_Stateless_alloc<_Rebound>) + // Only need room for the coroutine. + return __b.allocate(_Alloc_block::_M_cnt(__csz)); + else + { + auto __nsz = _Alloc_block::_M_cnt(_M_alloc_size(__csz)); + auto __f = __b.allocate(__nsz); + auto __fn = reinterpret_cast(__f); + auto __an = _M_alloc_address(__fn, __csz); + ::new (__an) _Rebound(std::move(__b)); + return __f; + } + } + + public: + void* + operator new(std::size_t __sz) + requires default_initializable<_Rebound> // _Alloc is non-void + { return _M_allocate({}, __sz); } + + template + void* + operator new(std::size_t __sz, + allocator_arg_t, const _Na& __na, + const _Args&...) + requires convertible_to + { + return _M_allocate(static_cast<_Rebound>(static_cast<_Alloc>(__na)), + __sz); + } + + template + void* + operator new(std::size_t __sz, + const _This&, + allocator_arg_t, const _Na& __na, + const _Args&...) + requires convertible_to + { + return _M_allocate(static_cast<_Rebound>(static_cast<_Alloc>(__na)), + __sz); + } + + void + operator delete(void* __ptr, std::size_t __csz) noexcept + { + if constexpr (_Stateless_alloc<_Rebound>) + { + _Rebound __b; + return __b.deallocate(reinterpret_cast<_Alloc_block*>(__ptr), + _Alloc_block::_M_cnt(__csz)); + } + else + { + auto __nsz = _Alloc_block::_M_cnt(_M_alloc_size(__csz)); + auto __fn = reinterpret_cast(__ptr); + auto __an = _M_alloc_address(__fn, __csz); + _Rebound __b(std::move(*__an)); + __an->~_Rebound(); + __b.deallocate(reinterpret_cast<_Alloc_block*>(__ptr), __nsz); + } + } + }; + + template<> + class _Promise_alloc + { + using _Dealloc_fn = void (*)(void*, std::size_t); + + static auto + _M_dealloc_address(std::uintptr_t __fn, std::uintptr_t __fsz) noexcept + { + auto __an = __fn + __fsz; + auto __ba = alignof(_Dealloc_fn); + auto __aligned = ((__an + __ba - 1) / __ba) * __ba; + return reinterpret_cast<_Dealloc_fn*>(__aligned); + } + + template + static auto + _M_alloc_address(std::uintptr_t __fn, std::uintptr_t __fsz) noexcept + requires (!_Stateless_alloc<_Rebound>) + { + auto __ba = alignof(_Rebound); + auto __da = _M_dealloc_address(__fn, __fsz); + auto __aan = reinterpret_cast(__da); + __aan += sizeof(_Dealloc_fn); + auto __aligned = ((__aan + __ba - 1) / __ba) * __ba; + return reinterpret_cast<_Rebound*>(__aligned); + } + + template + static auto + _M_alloc_size(std::size_t __csz) noexcept + { + // This time, we want the coroutine frame, then the deallocator + // pointer, then the allocator itself, if any. + std::size_t __aa = 0; + std::size_t __as = 0; + if constexpr (!std::same_as<_Rebound, void>) + { + __aa = alignof(_Rebound); + __as = sizeof(_Rebound); + } + auto __ba = __aa + alignof(_Dealloc_fn); + return __csz + __ba + __as + sizeof(_Dealloc_fn); + } + + template + static void + _M_deallocator(void* __ptr, std::size_t __csz) noexcept + { + auto __asz = _M_alloc_size<_Rebound>(__csz); + auto __nblk = _Alloc_block::_M_cnt(__asz); + + if constexpr (_Stateless_alloc<_Rebound>) + { + _Rebound __b; + __b.deallocate(reinterpret_cast<_Alloc_block*>(__ptr), __nblk); + } + else + { + auto __fn = reinterpret_cast(__ptr); + auto __an = _M_alloc_address<_Rebound>(__fn, __csz); + _Rebound __b(std::move(*__an)); + __an->~_Rebound(); + __b.deallocate(reinterpret_cast<_Alloc_block*>(__ptr), __nblk); + } + } + + template + static void* + _M_allocate(const _Na& __na, std::size_t __csz) + { + using _Rebound = typename std::allocator_traits<_Na> + ::template rebind_alloc<_Alloc_block>; + using _Rebound_ATr = typename std::allocator_traits<_Na> + ::template rebind_traits<_Alloc_block>; + + static_assert(is_pointer_v, + "Must use allocators for true pointers with generators"); + + _Dealloc_fn __d = &_M_deallocator<_Rebound>; + auto __b = static_cast<_Rebound>(__na); + auto __asz = _M_alloc_size<_Rebound>(__csz); + auto __nblk = _Alloc_block::_M_cnt(__asz); + void* __p = __b.allocate(__nblk); + auto __pn = reinterpret_cast(__p); + *_M_dealloc_address(__pn, __csz) = __d; + if constexpr (!_Stateless_alloc<_Rebound>) + { + auto __an = _M_alloc_address<_Rebound>(__pn, __csz); + ::new (__an) _Rebound(std::move(__b)); + } + return __p; + } + public: + void* + operator new(std::size_t __sz) + { + auto __nsz = _M_alloc_size(__sz); + _Dealloc_fn __d = [] (void* __ptr, std::size_t __sz) + { + ::operator delete(__ptr, _M_alloc_size(__sz)); + }; + auto __p = ::operator new(__nsz); + auto __pn = reinterpret_cast(__p); + *_M_dealloc_address(__pn, __sz) = __d; + return __p; + } + + template + void* + operator new(std::size_t __sz, + allocator_arg_t, const _Na& __na, + const _Args&...) + { return _M_allocate(__na, __sz); } + + template + void* + operator new(std::size_t __sz, + const _This&, + allocator_arg_t, const _Na& __na, + const _Args&...) + { return _M_allocate(__na, __sz); } + + void + operator delete(void* __ptr, std::size_t __sz) noexcept + { + _Dealloc_fn __d; + auto __pn = reinterpret_cast(__ptr); + __d = *_M_dealloc_address(__pn, __sz); + __d(__ptr, __sz); + } + }; + + template + concept _Cv_unqualified_object = is_object_v<_Tp> + && same_as<_Tp, remove_cv_t<_Tp>>; + } // namespace __gen + /// @endcond + + template + class generator + : public ranges::view_interface> + { + using _Value = __conditional_t, + remove_cvref_t<_Ref>, + _Val>; + static_assert(__gen::_Cv_unqualified_object<_Value>, + "Generator value must be a cv-unqualified object type"); + using _Reference = __gen::_Reference_t<_Ref, _Val>; + static_assert(is_reference_v<_Reference> + || (__gen::_Cv_unqualified_object<_Reference> + && copy_constructible<_Reference>), + "Generator reference type must be either a cv-unqualified " + "object type that is trivially constructible or a " + "reference type"); + + using _RRef = __conditional_t< + is_reference_v<_Reference>, + remove_reference_t<_Reference>&&, + _Reference>; + + /* Required to model indirectly_readable, and input_iterator. */ + static_assert(common_reference_with<_Reference&&, _Value&&>); + static_assert(common_reference_with<_Reference&&, _RRef&&>); + static_assert(common_reference_with<_RRef&&, const _Value&>); + + using _Yielded = __gen::_Yield_t<_Reference>; + using _Erased_promise = __gen::_Promise_erased<_Yielded>; + + struct _Iterator; + + friend _Erased_promise; + friend struct _Erased_promise::_Subyield_state; + public: + using yielded = _Yielded; + + struct promise_type : _Erased_promise, __gen::_Promise_alloc<_Alloc> + { + generator get_return_object() noexcept + { return { coroutine_handle::from_promise(*this) }; } + }; + +#ifdef __glibcxx_is_pointer_interconvertible + static_assert(is_pointer_interconvertible_base_of_v<_Erased_promise, + promise_type>); +#endif + + generator(const generator&) = delete; + + generator(generator&& __other) noexcept + : _M_coro(std::__exchange(__other._M_coro, nullptr)), + _M_began(std::__exchange(__other._M_began, false)) + {} + + ~generator() + { + if (auto& __c = this->_M_coro) + __c.destroy(); + } + + generator& + operator=(generator __other) noexcept + { + swap(__other._M_coro, this->_M_coro); + swap(__other._M_began, this->_M_began); + } + + _Iterator + begin() + { + this->_M_mark_as_started(); + auto __h = _Coro_handle::from_promise(_M_coro.promise()); + __h.promise()._M_nest._M_top() = __h; + return { __h }; + } + + default_sentinel_t + end() const noexcept + { return default_sentinel; } + + private: + using _Coro_handle = std::coroutine_handle<_Erased_promise>; + + generator(coroutine_handle __coro) noexcept + : _M_coro { move(__coro) } + {} + + void + _M_mark_as_started() noexcept + { + __glibcxx_assert(!this->_M_began); + this->_M_began = true; + } + + coroutine_handle _M_coro; + bool _M_began = false; + }; + + template + struct generator<_Ref, _Val, _Alloc>::_Iterator + { + using value_type = _Value; + using difference_type = ptrdiff_t; + + friend bool + operator==(const _Iterator& __i, default_sentinel_t) noexcept + { return __i._M_coro.done(); } + + friend class generator; + + _Iterator(_Iterator&& __o) noexcept + : _M_coro(std::__exchange(__o._M_coro, {})) + {} + + _Iterator& + operator=(_Iterator&& __o) noexcept + { + this->_M_coro = std::__exchange(__o._M_coro, {}); + return *this; + } + + _Iterator& + operator++() + { + _M_next(); + return *this; + } + + void + operator++(int) + { this->operator++(); } + + _Reference + operator*() + const noexcept(is_nothrow_move_constructible_v<_Reference>) + { + auto& __p = this->_M_coro.promise(); + return static_cast<_Reference>(*__p._M_value()); + } + + private: + friend class generator; + + _Iterator(_Coro_handle __g) + : _M_coro { __g } + { this->_M_next(); } + + void _M_next() + { + auto& __t = this->_M_coro.promise()._M_nest._M_top(); + __t.resume(); + } + + _Coro_handle _M_coro; + }; + + /// @} + +#if _GLIBCXX_HOSTED + namespace pmr { + template + using generator = std::generator<_Ref, _Val, polymorphic_allocator>; + } +#endif // HOSTED + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __cpp_lib_generator + +#endif // _GLIBCXX_GENERATOR diff --git a/template/sysroot/include/gfniintrin.h b/template/sysroot/include/gfniintrin.h new file mode 100644 index 0000000..a7ab9c4 --- /dev/null +++ b/template/sysroot/include/gfniintrin.h @@ -0,0 +1,430 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _GFNIINTRIN_H_INCLUDED +#define _GFNIINTRIN_H_INCLUDED + +#if !defined(__GFNI__) || !defined(__SSE2__) +#pragma GCC push_options +#pragma GCC target("gfni,sse2") +#define __DISABLE_GFNI__ +#endif /* __GFNI__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_gf2p8mul_epi8 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vgf2p8mulb_v16qi((__v16qi) __A, + (__v16qi) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_gf2p8affineinv_epi64_epi8 (__m128i __A, __m128i __B, const int __C) +{ + return (__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi ((__v16qi) __A, + (__v16qi) __B, + __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_gf2p8affine_epi64_epi8 (__m128i __A, __m128i __B, const int __C) +{ + return (__m128i) __builtin_ia32_vgf2p8affineqb_v16qi ((__v16qi) __A, + (__v16qi) __B, __C); +} +#else +#define _mm_gf2p8affineinv_epi64_epi8(A, B, C) \ + ((__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi((__v16qi)(__m128i)(A), \ + (__v16qi)(__m128i)(B), (int)(C))) +#define _mm_gf2p8affine_epi64_epi8(A, B, C) \ + ((__m128i) __builtin_ia32_vgf2p8affineqb_v16qi ((__v16qi)(__m128i)(A), \ + (__v16qi)(__m128i)(B), (int)(C))) +#endif + +#ifdef __DISABLE_GFNI__ +#undef __DISABLE_GFNI__ +#pragma GCC pop_options +#endif /* __DISABLE_GFNI__ */ + +#if !defined(__GFNI__) || !defined(__AVX__) +#pragma GCC push_options +#pragma GCC target("gfni,avx") +#define __DISABLE_GFNIAVX__ +#endif /* __GFNIAVX__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_gf2p8mul_epi8 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_vgf2p8mulb_v32qi ((__v32qi) __A, + (__v32qi) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_gf2p8affineinv_epi64_epi8 (__m256i __A, __m256i __B, const int __C) +{ + return (__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi ((__v32qi) __A, + (__v32qi) __B, + __C); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_gf2p8affine_epi64_epi8 (__m256i __A, __m256i __B, const int __C) +{ + return (__m256i) __builtin_ia32_vgf2p8affineqb_v32qi ((__v32qi) __A, + (__v32qi) __B, __C); +} +#else +#define _mm256_gf2p8affineinv_epi64_epi8(A, B, C) \ + ((__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi((__v32qi)(__m256i)(A), \ + (__v32qi)(__m256i)(B), \ + (int)(C))) +#define _mm256_gf2p8affine_epi64_epi8(A, B, C) \ + ((__m256i) __builtin_ia32_vgf2p8affineqb_v32qi ((__v32qi)(__m256i)(A), \ + ( __v32qi)(__m256i)(B), (int)(C))) +#endif + +#ifdef __DISABLE_GFNIAVX__ +#undef __DISABLE_GFNIAVX__ +#pragma GCC pop_options +#endif /* __GFNIAVX__ */ + +#if !defined(__GFNI__) || !defined(__AVX512VL__) +#pragma GCC push_options +#pragma GCC target("gfni,avx512vl") +#define __DISABLE_GFNIAVX512VL__ +#endif /* __GFNIAVX512VL__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_gf2p8mul_epi8 (__m128i __A, __mmask16 __B, __m128i __C, __m128i __D) +{ + return (__m128i) __builtin_ia32_vgf2p8mulb_v16qi_mask ((__v16qi) __C, + (__v16qi) __D, + (__v16qi)__A, __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_gf2p8mul_epi8 (__mmask16 __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vgf2p8mulb_v16qi_mask ((__v16qi) __B, + (__v16qi) __C, (__v16qi) _mm_avx512_setzero_si128 (), __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_gf2p8affineinv_epi64_epi8 (__m128i __A, __mmask16 __B, __m128i __C, + __m128i __D, const int __E) +{ + return (__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi_mask ((__v16qi) __C, + (__v16qi) __D, + __E, + (__v16qi)__A, + __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_gf2p8affineinv_epi64_epi8 (__mmask16 __A, __m128i __B, __m128i __C, + const int __D) +{ + return (__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi_mask ((__v16qi) __B, + (__v16qi) __C, __D, + (__v16qi) _mm_avx512_setzero_si128 (), + __A); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mask_gf2p8affine_epi64_epi8 (__m128i __A, __mmask16 __B, __m128i __C, + __m128i __D, const int __E) +{ + return (__m128i) __builtin_ia32_vgf2p8affineqb_v16qi_mask ((__v16qi) __C, + (__v16qi) __D, __E, (__v16qi)__A, __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskz_gf2p8affine_epi64_epi8 (__mmask16 __A, __m128i __B, __m128i __C, + const int __D) +{ + return (__m128i) __builtin_ia32_vgf2p8affineqb_v16qi_mask ((__v16qi) __B, + (__v16qi) __C, __D, (__v16qi) _mm_avx512_setzero_si128 (), __A); +} +#else +#define _mm_mask_gf2p8affineinv_epi64_epi8(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi_mask( \ + (__v16qi)(__m128i)(C), (__v16qi)(__m128i)(D), \ + (int)(E), (__v16qi)(__m128i)(A), (__mmask16)(B))) +#define _mm_maskz_gf2p8affineinv_epi64_epi8(A, B, C, D) \ + ((__m128i) __builtin_ia32_vgf2p8affineinvqb_v16qi_mask( \ + (__v16qi)(__m128i)(B), (__v16qi)(__m128i)(C), \ + (int)(D), (__v16qi)(__m128i) _mm_avx512_setzero_si128 (), \ + (__mmask16)(A))) +#define _mm_mask_gf2p8affine_epi64_epi8(A, B, C, D, E) \ + ((__m128i) __builtin_ia32_vgf2p8affineqb_v16qi_mask((__v16qi)(__m128i)(C),\ + (__v16qi)(__m128i)(D), (int)(E), (__v16qi)(__m128i)(A), (__mmask16)(B))) +#define _mm_maskz_gf2p8affine_epi64_epi8(A, B, C, D) \ + ((__m128i) __builtin_ia32_vgf2p8affineqb_v16qi_mask((__v16qi)(__m128i)(B),\ + (__v16qi)(__m128i)(C), (int)(D), \ + (__v16qi)(__m128i) _mm_avx512_setzero_si128 (), (__mmask16)(A))) +#endif + +#ifdef __DISABLE_GFNIAVX512VL__ +#undef __DISABLE_GFNIAVX512VL__ +#pragma GCC pop_options +#endif /* __GFNIAVX512VL__ */ + +#if !defined(__GFNI__) || !defined(__AVX512VL__) || !defined(__AVX512BW__) +#pragma GCC push_options +#pragma GCC target("gfni,avx512vl,avx512bw") +#define __DISABLE_GFNIAVX512VLBW__ +#endif /* __GFNIAVX512VLBW__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_gf2p8mul_epi8 (__m256i __A, __mmask32 __B, __m256i __C, + __m256i __D) +{ + return (__m256i) __builtin_ia32_vgf2p8mulb_v32qi_mask ((__v32qi) __C, + (__v32qi) __D, + (__v32qi)__A, __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_gf2p8mul_epi8 (__mmask32 __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vgf2p8mulb_v32qi_mask ((__v32qi) __B, + (__v32qi) __C, (__v32qi) _mm256_avx512_setzero_si256 (), __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_gf2p8affineinv_epi64_epi8 (__m256i __A, __mmask32 __B, + __m256i __C, __m256i __D, const int __E) +{ + return (__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi_mask ((__v32qi) __C, + (__v32qi) __D, + __E, + (__v32qi)__A, + __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_gf2p8affineinv_epi64_epi8 (__mmask32 __A, __m256i __B, + __m256i __C, const int __D) +{ + return (__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi_mask ((__v32qi) __B, + (__v32qi) __C, __D, + (__v32qi) _mm256_avx512_setzero_si256 (), __A); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_mask_gf2p8affine_epi64_epi8 (__m256i __A, __mmask32 __B, __m256i __C, + __m256i __D, const int __E) +{ + return (__m256i) __builtin_ia32_vgf2p8affineqb_v32qi_mask ((__v32qi) __C, + (__v32qi) __D, + __E, + (__v32qi)__A, + __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_maskz_gf2p8affine_epi64_epi8 (__mmask32 __A, __m256i __B, + __m256i __C, const int __D) +{ + return (__m256i) __builtin_ia32_vgf2p8affineqb_v32qi_mask ((__v32qi) __B, + (__v32qi) __C, __D, (__v32qi)_mm256_avx512_setzero_si256 (), __A); +} +#else +#define _mm256_mask_gf2p8affineinv_epi64_epi8(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi_mask( \ + (__v32qi)(__m256i)(C), (__v32qi)(__m256i)(D), (int)(E), \ + (__v32qi)(__m256i)(A), (__mmask32)(B))) +#define _mm256_maskz_gf2p8affineinv_epi64_epi8(A, B, C, D) \ + ((__m256i) __builtin_ia32_vgf2p8affineinvqb_v32qi_mask( \ + (__v32qi)(__m256i)(B), (__v32qi)(__m256i)(C), (int)(D), \ + (__v32qi)(__m256i) _mm256_avx512_setzero_si256 (), (__mmask32)(A))) +#define _mm256_mask_gf2p8affine_epi64_epi8(A, B, C, D, E) \ + ((__m256i) __builtin_ia32_vgf2p8affineqb_v32qi_mask((__v32qi)(__m256i)(C),\ + (__v32qi)(__m256i)(D), (int)(E), (__v32qi)(__m256i)(A), (__mmask32)(B))) +#define _mm256_maskz_gf2p8affine_epi64_epi8(A, B, C, D) \ + ((__m256i) __builtin_ia32_vgf2p8affineqb_v32qi_mask((__v32qi)(__m256i)(B),\ + (__v32qi)(__m256i)(C), (int)(D), \ + (__v32qi)(__m256i) _mm256_avx512_setzero_si256 (), (__mmask32)(A))) +#endif + +#ifdef __DISABLE_GFNIAVX512VLBW__ +#undef __DISABLE_GFNIAVX512VLBW__ +#pragma GCC pop_options +#endif /* __GFNIAVX512VLBW__ */ + +#if !defined(__GFNI__) || !defined(__EVEX512__) || !defined(__AVX512F__) +#pragma GCC push_options +#pragma GCC target("gfni,avx512f,evex512") +#define __DISABLE_GFNIAVX512F__ +#endif /* __GFNIAVX512F__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_gf2p8mul_epi8 (__m512i __A, __m512i __B) +{ + return (__m512i) __builtin_ia32_vgf2p8mulb_v64qi ((__v64qi) __A, + (__v64qi) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_gf2p8affineinv_epi64_epi8 (__m512i __A, __m512i __B, const int __C) +{ + return (__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi ((__v64qi) __A, + (__v64qi) __B, __C); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_gf2p8affine_epi64_epi8 (__m512i __A, __m512i __B, const int __C) +{ + return (__m512i) __builtin_ia32_vgf2p8affineqb_v64qi ((__v64qi) __A, + (__v64qi) __B, __C); +} +#else +#define _mm512_gf2p8affineinv_epi64_epi8(A, B, C) \ + ((__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi ( \ + (__v64qi)(__m512i)(A), (__v64qi)(__m512i)(B), (int)(C))) +#define _mm512_gf2p8affine_epi64_epi8(A, B, C) \ + ((__m512i) __builtin_ia32_vgf2p8affineqb_v64qi ((__v64qi)(__m512i)(A), \ + (__v64qi)(__m512i)(B), (int)(C))) +#endif + +#ifdef __DISABLE_GFNIAVX512F__ +#undef __DISABLE_GFNIAVX512F__ +#pragma GCC pop_options +#endif /* __GFNIAVX512F__ */ + +#if !defined(__GFNI__) || !defined(__EVEX512__) || !defined(__AVX512BW__) +#pragma GCC push_options +#pragma GCC target("gfni,avx512bw,evex512") +#define __DISABLE_GFNIAVX512FBW__ +#endif /* __GFNIAVX512FBW__ */ + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_gf2p8mul_epi8 (__m512i __A, __mmask64 __B, __m512i __C, + __m512i __D) +{ + return (__m512i) __builtin_ia32_vgf2p8mulb_v64qi_mask ((__v64qi) __C, + (__v64qi) __D, (__v64qi)__A, __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_gf2p8mul_epi8 (__mmask64 __A, __m512i __B, __m512i __C) +{ + return (__m512i) __builtin_ia32_vgf2p8mulb_v64qi_mask ((__v64qi) __B, + (__v64qi) __C, (__v64qi) _mm512_setzero_si512 (), __A); +} + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_gf2p8affineinv_epi64_epi8 (__m512i __A, __mmask64 __B, __m512i __C, + __m512i __D, const int __E) +{ + return (__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi_mask ((__v64qi) __C, + (__v64qi) __D, + __E, + (__v64qi)__A, + __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_gf2p8affineinv_epi64_epi8 (__mmask64 __A, __m512i __B, + __m512i __C, const int __D) +{ + return (__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi_mask ((__v64qi) __B, + (__v64qi) __C, __D, + (__v64qi) _mm512_setzero_si512 (), __A); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_mask_gf2p8affine_epi64_epi8 (__m512i __A, __mmask64 __B, __m512i __C, + __m512i __D, const int __E) +{ + return (__m512i) __builtin_ia32_vgf2p8affineqb_v64qi_mask ((__v64qi) __C, + (__v64qi) __D, __E, (__v64qi)__A, __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_maskz_gf2p8affine_epi64_epi8 (__mmask64 __A, __m512i __B, __m512i __C, + const int __D) +{ + return (__m512i) __builtin_ia32_vgf2p8affineqb_v64qi_mask ((__v64qi) __B, + (__v64qi) __C, __D, (__v64qi) _mm512_setzero_si512 (), __A); +} +#else +#define _mm512_mask_gf2p8affineinv_epi64_epi8(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi_mask( \ + (__v64qi)(__m512i)(C), (__v64qi)(__m512i)(D), (int)(E), \ + (__v64qi)(__m512i)(A), (__mmask64)(B))) +#define _mm512_maskz_gf2p8affineinv_epi64_epi8(A, B, C, D) \ + ((__m512i) __builtin_ia32_vgf2p8affineinvqb_v64qi_mask( \ + (__v64qi)(__m512i)(B), (__v64qi)(__m512i)(C), (int)(D), \ + (__v64qi)(__m512i) _mm512_setzero_si512 (), (__mmask64)(A))) +#define _mm512_mask_gf2p8affine_epi64_epi8(A, B, C, D, E) \ + ((__m512i) __builtin_ia32_vgf2p8affineqb_v64qi_mask((__v64qi)(__m512i)(C),\ + (__v64qi)(__m512i)(D), (int)(E), (__v64qi)(__m512i)(A), (__mmask64)(B))) +#define _mm512_maskz_gf2p8affine_epi64_epi8(A, B, C, D) \ + ((__m512i) __builtin_ia32_vgf2p8affineqb_v64qi_mask((__v64qi)(__m512i)(B),\ + (__v64qi)(__m512i)(C), (int)(D), \ + (__v64qi)(__m512i) _mm512_setzero_si512 (), (__mmask64)(A))) +#endif + +#ifdef __DISABLE_GFNIAVX512FBW__ +#undef __DISABLE_GFNIAVX512FBW__ +#pragma GCC pop_options +#endif /* __GFNIAVX512FBW__ */ + +#endif /* _GFNIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/gui/canvas.hpp b/template/sysroot/include/gui/canvas.hpp new file mode 100644 index 0000000..fda9d62 --- /dev/null +++ b/template/sysroot/include/gui/canvas.hpp @@ -0,0 +1,251 @@ +/* + * canvas.hpp + * MontaukOS Canvas — drawing primitives for pixel buffer (uint32_t*) targets + * Mirrors Framebuffer API but operates directly on app content buffers. + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/font.hpp" +#include "gui/svg.hpp" +#include "gui/window.hpp" + +namespace gui { + +struct Canvas { + uint32_t* pixels; + int w, h; + + // ---- Constructors ---- + + Canvas(uint32_t* px, int width, int height) + : pixels(px), w(width), h(height) {} + + Canvas(Window* win) + : pixels(win->content), w(win->content_w), h(win->content_h) {} + + // ---- Core drawing ---- + + void fill(Color c) { + uint32_t px = c.to_pixel(); + uint64_t px2 = ((uint64_t)px << 32) | px; + int total = w * h; + int i = 0; + // Align to 8-byte boundary if needed + if (total > 0 && ((uint64_t)pixels & 4)) { + pixels[0] = px; + i = 1; + } + uint64_t* dst64 = (uint64_t*)(pixels + i); + int pairs = (total - i) / 2; + for (int p = 0; p < pairs; p++) dst64[p] = px2; + if ((total - i) & 1) pixels[total - 1] = px; + } + + void put_pixel(int x, int y, Color c) { + if (x >= 0 && x < w && y >= 0 && y < h) + pixels[y * w + x] = c.to_pixel(); + } + + void fill_rect(int x, int y, int rw, int rh, Color c) { + uint32_t px = c.to_pixel(); + uint64_t px2 = ((uint64_t)px << 32) | px; + int x0 = gui_max(x, 0), y0 = gui_max(y, 0); + int x1 = gui_min(x + rw, w), y1 = gui_min(y + rh, h); + for (int dy = y0; dy < y1; dy++) { + uint32_t* row = pixels + dy * w; + int dx = x0; + // Align to 8-byte boundary + if (dx < x1 && ((uint64_t)(row + dx) & 4)) { + row[dx] = px; + dx++; + } + // Bulk 2-pixel writes + uint64_t* dst64 = (uint64_t*)(row + dx); + int pairs = (x1 - dx) / 2; + for (int p = 0; p < pairs; p++) dst64[p] = px2; + dx += pairs * 2; + // Remainder + if (dx < x1) row[dx] = px; + } + } + + void fill_rounded_rect(int x, int y, int rw, int rh, int radius, Color c) { + if (radius <= 0) { fill_rect(x, y, rw, rh, c); return; } + uint32_t px = c.to_pixel(); + for (int row = 0; row < rh; row++) { + int dy = y + row; + if (dy < 0 || dy >= h) continue; + for (int col = 0; col < rw; col++) { + int dx = x + col; + if (dx < 0 || dx >= w) continue; + bool in_corner = false; + int cx_off = 0, cy_off = 0; + if (col < radius && row < radius) { + cx_off = radius - col; cy_off = radius - row; in_corner = true; + } else if (col >= rw - radius && row < radius) { + cx_off = col - (rw - radius - 1); cy_off = radius - row; in_corner = true; + } else if (col < radius && row >= rh - radius) { + cx_off = radius - col; cy_off = row - (rh - radius - 1); in_corner = true; + } else if (col >= rw - radius && row >= rh - radius) { + cx_off = col - (rw - radius - 1); cy_off = row - (rh - radius - 1); in_corner = true; + } + if (in_corner && cx_off * cx_off + cy_off * cy_off > radius * radius) continue; + pixels[dy * w + dx] = px; + } + } + } + + void hline(int x, int y, int len, Color c) { + if (y < 0 || y >= h) return; + uint32_t px = c.to_pixel(); + int x0 = gui_max(x, 0), x1 = gui_min(x + len, w); + uint32_t* row = pixels + y * w; + int dx = x0; + if (dx < x1 && ((uint64_t)(row + dx) & 4)) { + row[dx] = px; + dx++; + } + uint64_t px2 = ((uint64_t)px << 32) | px; + uint64_t* dst64 = (uint64_t*)(row + dx); + int pairs = (x1 - dx) / 2; + for (int p = 0; p < pairs; p++) dst64[p] = px2; + dx += pairs * 2; + if (dx < x1) row[dx] = px; + } + + void vline(int x, int y, int len, Color c) { + if (x < 0 || x >= w) return; + uint32_t px = c.to_pixel(); + int y0 = gui_max(y, 0), y1 = gui_min(y + len, h); + for (int dy = y0; dy < y1; dy++) + pixels[dy * w + x] = px; + } + + void rect(int x, int y, int rw, int rh, Color c) { + hline(x, y, rw, c); + hline(x, y + rh - 1, rw, c); + vline(x, y, rh, c); + vline(x + rw - 1, y, rh, c); + } + + // ---- Text ---- + + void text(int x, int y, const char* str, Color c) { + if (fonts::system_font && fonts::system_font->valid) { + fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::UI_SIZE); + return; + } + uint32_t px = c.to_pixel(); + for (int i = 0; str[i] && x + (i + 1) * FONT_WIDTH <= w; i++) { + const uint8_t* glyph = &font_data[(unsigned char)str[i] * FONT_HEIGHT]; + int cx = x + i * FONT_WIDTH; + for (int fy = 0; fy < FONT_HEIGHT && y + fy < h; fy++) { + uint8_t bits = glyph[fy]; + for (int fx = 0; fx < FONT_WIDTH; fx++) { + if (bits & (0x80 >> fx)) { + int dx = cx + fx; + int dy = y + fy; + if (dx >= 0 && dx < w && dy >= 0) + pixels[dy * w + dx] = px; + } + } + } + } + } + + void text_2x(int x, int y, const char* str, Color c) { + if (fonts::system_font && fonts::system_font->valid) { + fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::LARGE_SIZE); + return; + } + uint32_t px = c.to_pixel(); + for (int i = 0; str[i] && x + (i + 1) * FONT_WIDTH * 2 <= w; i++) { + const uint8_t* glyph = &font_data[(unsigned char)str[i] * FONT_HEIGHT]; + int cx = x + i * FONT_WIDTH * 2; + for (int fy = 0; fy < FONT_HEIGHT; fy++) { + uint8_t bits = glyph[fy]; + for (int fx = 0; fx < FONT_WIDTH; fx++) { + if (bits & (0x80 >> fx)) { + int dx = cx + fx * 2; + int dy = y + fy * 2; + for (int sy = 0; sy < 2; sy++) + for (int sx = 0; sx < 2; sx++) { + int pdx = dx + sx; + int pdy = dy + sy; + if (pdx >= 0 && pdx < w && pdy >= 0 && pdy < h) + pixels[pdy * w + pdx] = px; + } + } + } + } + } + } + + void text_mono(int x, int y, const char* str, Color c) { + if (fonts::mono && fonts::mono->valid) { + fonts::mono->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::TERM_SIZE); + return; + } + text(x, y, str, c); + } + + // ---- Icons ---- + + void icon(int x, int y, const SvgIcon& ic) { + if (!ic.pixels) return; + for (int row = 0; row < ic.height; row++) { + int dy = y + row; + if (dy < 0 || dy >= h) continue; + for (int col = 0; col < ic.width; col++) { + int dx = x + col; + if (dx < 0 || dx >= w) continue; + uint32_t src = ic.pixels[row * ic.width + col]; + uint8_t sa = (src >> 24) & 0xFF; + if (sa == 0) continue; + if (sa == 255) { + pixels[dy * w + dx] = src; + } else { + uint32_t dst = pixels[dy * w + dx]; + uint8_t sr = (src >> 16) & 0xFF; + uint8_t sg = (src >> 8) & 0xFF; + uint8_t sb = src & 0xFF; + uint8_t dr = (dst >> 16) & 0xFF; + uint8_t dg = (dst >> 8) & 0xFF; + uint8_t db = dst & 0xFF; + uint32_t a = sa, inv_a = 255 - sa; + uint32_t rr = (a * sr + inv_a * dr + 128) / 255; + uint32_t gg = (a * sg + inv_a * dg + 128) / 255; + uint32_t bb = (a * sb + inv_a * db + 128) / 255; + pixels[dy * w + dx] = 0xFF000000 | (rr << 16) | (gg << 8) | bb; + } + } + } + } + + // ---- High-level helpers ---- + + void kv_line(int x, int* y, const char* line, Color c, int line_h = 0) { + if (line_h == 0) line_h = system_font_height() + 6; + text(x, *y, line, c); + *y += line_h; + } + + void separator(int x_start, int x_end, int* y, Color c, int spacing = 8) { + hline(x_start, *y, x_end - x_start, c); + *y += spacing; + } + + void button(int x, int y, int bw, int bh, const char* label, + Color bg, Color fg, int radius = 4) { + fill_rounded_rect(x, y, bw, bh, radius, bg); + int tw = text_width(label); + int fh = system_font_height(); + int tx = x + (bw - tw) / 2; + int ty = y + (bh - fh) / 2; + text(tx, ty, label, fg); + } +}; + +} // namespace gui diff --git a/template/sysroot/include/gui/desktop.hpp b/template/sysroot/include/gui/desktop.hpp new file mode 100644 index 0000000..098b678 --- /dev/null +++ b/template/sysroot/include/gui/desktop.hpp @@ -0,0 +1,161 @@ +/* + * desktop.hpp + * MontaukOS desktop state and compositor declarations + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" +#include "gui/svg.hpp" +#include "gui/window.hpp" +#include "gui/widgets.hpp" +#include "gui/terminal.hpp" +#include + +namespace gui { + +static constexpr int MAX_WINDOWS = 8; +static constexpr int PANEL_HEIGHT = 32; +static constexpr int MAX_EXTERNAL_APPS = 16; + +// External app discovered from 0:/apps/ manifest +struct ExternalApp { + char name[48]; + char binary_path[128]; + char category[24]; + SvgIcon icon; + bool menu_visible; +}; + +struct DesktopSettings { + // Background + bool bg_gradient; // true = gradient, false = solid + bool bg_image; // true = JPEG wallpaper + Color bg_solid; // solid background color + Color bg_grad_top; // gradient top color + Color bg_grad_bottom; // gradient bottom color + + // Wallpaper (valid when bg_image == true) + char bg_image_path[128]; // VFS path to current wallpaper + uint32_t* bg_wallpaper; // scaled ARGB pixel buffer (screen-sized) + int bg_wallpaper_w; // scaled width + int bg_wallpaper_h; // scaled height + + // Panel + Color panel_color; // panel background color + + // Accent + Color accent_color; // buttons, highlights, active indicators + + // Display + bool show_shadows; // window shadows on/off + bool clock_24h; // 24-hour clock format + int ui_scale; // 0=Small, 1=Default, 2=Large +}; + +struct DesktopState { + Framebuffer fb; + Window windows[MAX_WINDOWS]; + int window_count; + int focused_window; + + // Current user context + char current_user[32]; + char home_dir[128]; // "0:/users/" + char user_config_dir[128]; // "0:/users//config" + bool is_admin; + + Montauk::MouseState mouse; + uint8_t prev_buttons; + + bool app_menu_open; + + SvgIcon icon_terminal; + SvgIcon icon_filemanager; + SvgIcon icon_sysinfo; + SvgIcon icon_appmenu; + SvgIcon icon_folder; + SvgIcon icon_file; + SvgIcon icon_computer; + SvgIcon icon_network; + SvgIcon icon_calculator; + SvgIcon icon_texteditor; + SvgIcon icon_go_up; + SvgIcon icon_go_back; + SvgIcon icon_go_forward; + SvgIcon icon_save; + SvgIcon icon_home; + SvgIcon icon_exec; + SvgIcon icon_wikipedia; + + SvgIcon icon_folder_lg; + SvgIcon icon_file_lg; + SvgIcon icon_exec_lg; + SvgIcon icon_drive; + SvgIcon icon_drive_lg; + SvgIcon icon_delete; + + SvgIcon icon_settings; + SvgIcon icon_reboot; + SvgIcon icon_shutdown; + SvgIcon icon_logout; + + SvgIcon icon_procmgr; + SvgIcon icon_mandelbrot; + SvgIcon icon_volume; + + // External apps discovered from 0:/apps/ manifests + ExternalApp external_apps[MAX_EXTERNAL_APPS]; + int external_app_count; + + bool ctx_menu_open; + int ctx_menu_x, ctx_menu_y; + + bool net_popup_open; + Montauk::NetCfg cached_net_cfg; + uint64_t net_cfg_last_poll; + Rect net_icon_rect; + + bool vol_popup_open; + Rect vol_icon_rect; + int vol_level; // 0-100 + bool vol_muted; + int vol_pre_mute; // volume before mute + bool vol_dragging; // slider drag in progress + uint64_t vol_last_poll; + + int screen_w, screen_h; + + // IDs of external windows we've sent a close event to but that haven't + // been destroyed yet by their owning process. Prevents the poll loop + // from re-creating them at the default position (visible flicker). + static constexpr int MAX_CLOSING = 8; + int closing_ext_ids[MAX_CLOSING]; + int closing_ext_count; + + DesktopSettings settings; + + // Lock screen state + bool screen_locked; + char lock_password[64]; + int lock_password_len; + char lock_error[128]; + bool lock_show_error; + char lock_display_name[64]; + SvgIcon icon_lock; +}; + +// Forward declarations - implemented in main.cpp +void desktop_init(DesktopState* ds); +void desktop_run(DesktopState* ds); +void desktop_compose(DesktopState* ds); +int desktop_create_window(DesktopState* ds, const char* title, int x, int y, int w, int h); +void desktop_close_window(DesktopState* ds, int idx); +void desktop_raise_window(DesktopState* ds, int idx); +void desktop_draw_panel(DesktopState* ds); +void desktop_draw_window(DesktopState* ds, int idx); +void desktop_handle_mouse(DesktopState* ds); +void desktop_handle_keyboard(DesktopState* ds, const Montauk::KeyEvent& key); + +} // namespace gui diff --git a/template/sysroot/include/gui/draw.hpp b/template/sysroot/include/gui/draw.hpp new file mode 100644 index 0000000..ab77a9c --- /dev/null +++ b/template/sysroot/include/gui/draw.hpp @@ -0,0 +1,394 @@ +/* + * draw.hpp + * MontaukOS drawing primitives (lines, circles, rounded rects, cursor) + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" + +namespace gui { + +// Fast horizontal line +inline void draw_hline(Framebuffer& fb, int x, int y, int w, Color c) { + for (int i = 0; i < w; i++) fb.put_pixel(x + i, y, c); +} + +// Fast vertical line +inline void draw_vline(Framebuffer& fb, int x, int y, int h, Color c) { + for (int i = 0; i < h; i++) fb.put_pixel(x, y + i, c); +} + +// Rectangle outline +inline void draw_rect(Framebuffer& fb, int x, int y, int w, int h, Color c) { + draw_hline(fb, x, y, w, c); + draw_hline(fb, x, y + h - 1, w, c); + draw_vline(fb, x, y, h, c); + draw_vline(fb, x + w - 1, y, h, c); +} + +// Filled rounded rectangle using corner circles +inline void fill_rounded_rect(Framebuffer& fb, int x, int y, int w, int h, int radius, Color c) { + if (radius <= 0) { + fb.fill_rect(x, y, w, h, c); + return; + } + + // Clamp radius to half the smaller dimension + int max_r = gui_min(w / 2, h / 2); + if (radius > max_r) radius = max_r; + + // Fill the center rectangle + fb.fill_rect(x + radius, y, w - 2 * radius, h, c); + // Fill the left and right strips (excluding corners) + fb.fill_rect(x, y + radius, radius, h - 2 * radius, c); + fb.fill_rect(x + w - radius, y + radius, radius, h - 2 * radius, c); + + // Draw the four rounded corners using midpoint circle + int cx_tl = x + radius; + int cy_tl = y + radius; + int cx_tr = x + w - radius - 1; + int cy_tr = y + radius; + int cx_bl = x + radius; + int cy_bl = y + h - radius - 1; + int cx_br = x + w - radius - 1; + int cy_br = y + h - radius - 1; + + int px = 0; + int py = radius; + int d = 1 - radius; + + while (px <= py) { + // Top-left corner + draw_hline(fb, cx_tl - py, cy_tl - px, py - radius + radius, c); + draw_hline(fb, cx_tl - px, cy_tl - py, px, c); + + // Top-right corner + draw_hline(fb, cx_tr + 1, cy_tr - px, py, c); + draw_hline(fb, cx_tr + 1, cy_tr - py, px, c); + + // Bottom-left corner + draw_hline(fb, cx_bl - py, cy_bl + px, py, c); + draw_hline(fb, cx_bl - px, cy_bl + py, px, c); + + // Bottom-right corner + draw_hline(fb, cx_br + 1, cy_br + px, py, c); + draw_hline(fb, cx_br + 1, cy_br + py, px, c); + + if (d < 0) { + d += 2 * px + 3; + } else { + d += 2 * (px - py) + 5; + py--; + } + px++; + } +} + +// Filled circle (midpoint algorithm) +inline void fill_circle(Framebuffer& fb, int cx, int cy, int r, Color c) { + if (r <= 0) return; + + int x = 0; + int y = r; + int d = 1 - r; + + // Draw initial horizontal lines + draw_hline(fb, cx - r, cy, 2 * r + 1, c); + + while (x < y) { + if (d < 0) { + d += 2 * x + 3; + } else { + d += 2 * (x - y) + 5; + y--; + draw_hline(fb, cx - x, cy + y + 1, 2 * x + 1, c); + draw_hline(fb, cx - x, cy - y - 1, 2 * x + 1, c); + } + x++; + draw_hline(fb, cx - y, cy + x, 2 * y + 1, c); + draw_hline(fb, cx - y, cy - x, 2 * y + 1, c); + } +} + +// Circle outline (midpoint algorithm) +inline void draw_circle(Framebuffer& fb, int cx, int cy, int r, Color c) { + if (r <= 0) { + fb.put_pixel(cx, cy, c); + return; + } + + int x = 0; + int y = r; + int d = 1 - r; + + while (x <= y) { + fb.put_pixel(cx + x, cy + y, c); + fb.put_pixel(cx - x, cy + y, c); + fb.put_pixel(cx + x, cy - y, c); + fb.put_pixel(cx - x, cy - y, c); + fb.put_pixel(cx + y, cy + x, c); + fb.put_pixel(cx - y, cy + x, c); + fb.put_pixel(cx + y, cy - x, c); + fb.put_pixel(cx - y, cy - x, c); + + if (d < 0) { + d += 2 * x + 3; + } else { + d += 2 * (x - y) + 5; + y--; + } + x++; + } +} + +// Bresenham line drawing +inline void draw_line(Framebuffer& fb, int x0, int y0, int x1, int y1, Color c) { + int dx = gui_abs(x1 - x0); + int dy = gui_abs(y1 - y0); + int sx = x0 < x1 ? 1 : -1; + int sy = y0 < y1 ? 1 : -1; + int err = dx - dy; + + for (;;) { + fb.put_pixel(x0, y0, c); + if (x0 == x1 && y0 == y1) break; + int e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } +} + +// Drop shadow: offset darker rectangles below/right +inline void draw_shadow(Framebuffer& fb, int x, int y, int w, int h, int offset, Color shadow_color) { + // Bottom shadow strip + fb.fill_rect_alpha(x + offset, y + h, w, offset, shadow_color); + // Right shadow strip + fb.fill_rect_alpha(x + w, y + offset, offset, h, shadow_color); + // Corner + fb.fill_rect_alpha(x + w, y + h, offset, offset, shadow_color); +} + +// 16x16 mouse cursor bitmaps +// Outline (black, where design has '1') +static constexpr uint16_t cursor_outline[16] = { + 0x8000, // 1000000000000000 + 0xC000, // 1100000000000000 + 0xA000, // 1010000000000000 + 0x9000, // 1001000000000000 + 0x8800, // 1000100000000000 + 0x8400, // 1000010000000000 + 0x8200, // 1000001000000000 + 0x8100, // 1000000100000000 + 0x8080, // 1000000010000000 + 0x8040, // 1000000001000000 + 0x8780, // 1000011110000000 (changed: row 10 = 1 2 2 2 2 2 1 1 1 1) + 0x9200, // 1001001000000000 (row 11 = 1 2 2 1 2 2 1) + 0xA900, // 1010100100000000 (row 12 = 1 2 1 0 1 2 2 1) + 0xC900, // 1100100100000000 (row 13 = 1 1 0 0 1 2 2 1) + 0x8480, // 1000010010000000 (row 14 = 1 0 0 0 0 1 2 2 1) + 0x0700, // 0000011100000000 (row 15 = 0 0 0 0 0 1 1 1) +}; + +// Fill (white, where design has '2') +static constexpr uint16_t cursor_fill[16] = { + 0x0000, // row 0: no fill + 0x0000, // row 1: no fill + 0x4000, // row 2: 0100000000000000 + 0x6000, // row 3: 0110000000000000 + 0x7000, // row 4: 0111000000000000 + 0x7800, // row 5: 0111100000000000 + 0x7C00, // row 6: 0111110000000000 + 0x7E00, // row 7: 0111111000000000 + 0x7F00, // row 8: 0111111100000000 + 0x7F80, // row 9: 0111111110000000 + 0x7800, // row 10: 0111100000000000 (fill only in positions 1-5) + 0x6C00, // row 11: 0110110000000000 (fill at positions 1,2 and 4,5) + 0x4600, // row 12: 0100011000000000 (fill at position 1 and 5,6) + 0x0600, // row 13: 0000011000000000 (fill at positions 5,6) + 0x0300, // row 14: 0000001100000000 (fill at positions 6,7) + 0x0000, // row 15: no fill +}; + +// Resize cursor: horizontal double arrow (left-right) +static constexpr uint16_t cursor_h_resize_outline[16] = { + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0820, // 0000100000100000 + 0x1830, // 0001100000110000 + 0x3FF8, // 0011111111111000 + 0x7FFC, // 0111111111111100 + 0x3FF8, // 0011111111111000 + 0x1830, // 0001100000110000 + 0x0820, // 0000100000100000 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; +static constexpr uint16_t cursor_h_resize_fill[16] = { + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, + 0x0000, + 0x1FF0, // 0001111111110000 + 0x3FF8, // 0011111111111000 + 0x1FF0, // 0001111111110000 + 0x0000, + 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +// Resize cursor: vertical double arrow (up-down) +static constexpr uint16_t cursor_v_resize_outline[16] = { + 0x0000, 0x0000, + 0x0200, // 0000001000000000 + 0x0700, // 0000011100000000 + 0x0F80, // 0000111110000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0F80, // 0000111110000000 + 0x0700, // 0000011100000000 + 0x0200, // 0000001000000000 + 0x0000, 0x0000, +}; +static constexpr uint16_t cursor_v_resize_fill[16] = { + 0x0000, 0x0000, 0x0000, + 0x0200, // 0000001000000000 + 0x0700, // 0000011100000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0200, // 0000001000000000 + 0x0700, // 0000011100000000 + 0x0200, // 0000001000000000 + 0x0000, 0x0000, 0x0000, +}; + +// Resize cursor: diagonal NW-SE double arrow +static constexpr uint16_t cursor_nwse_resize_outline[16] = { + 0x0000, 0x0000, + 0x7C00, // 0111110000000000 + 0x6000, // 0110000000000000 + 0x5000, // 0101000000000000 + 0x4800, // 0100100000000000 + 0x2400, // 0010010000000000 + 0x1200, // 0001001000000000 + 0x0900, // 0000100100000000 + 0x0480, // 0000010010000000 + 0x0240, // 0000001001000000 + 0x0140, // 0000000101000000 + 0x00C0, // 0000000011000000 + 0x07C0, // 0000011111000000 + 0x0000, 0x0000, +}; +static constexpr uint16_t cursor_nwse_resize_fill[16] = { + 0x0000, 0x0000, 0x0000, + 0x1C00, // 0001110000000000 + 0x2800, // 0010100000000000 + 0x0400, // 0000010000000000 + 0x0200, // 0000001000000000 + 0x0100, // 0000000100000000 + 0x0080, // 0000000010000000 + 0x0040, // 0000000001000000 + 0x0280, // 0000001010000000 + 0x0380, // 0000001110000000 + 0x0000, 0x0000, 0x0000, 0x0000, +}; + +// Resize cursor: diagonal NE-SW double arrow +static constexpr uint16_t cursor_nesw_resize_outline[16] = { + 0x0000, 0x0000, + 0x07C0, // 0000011111000000 + 0x00C0, // 0000000011000000 + 0x0140, // 0000000101000000 + 0x0240, // 0000001001000000 + 0x0480, // 0000010010000000 + 0x0900, // 0000100100000000 + 0x1200, // 0001001000000000 + 0x2400, // 0010010000000000 + 0x4800, // 0100100000000000 + 0x5000, // 0101000000000000 + 0x6000, // 0110000000000000 + 0x7C00, // 0111110000000000 + 0x0000, 0x0000, +}; +static constexpr uint16_t cursor_nesw_resize_fill[16] = { + 0x0000, 0x0000, 0x0000, + 0x0380, // 0000001110000000 + 0x0280, // 0000001010000000 + 0x0040, // 0000000001000000 + 0x0080, // 0000000010000000 + 0x0100, // 0000000100000000 + 0x0200, // 0000001000000000 + 0x0400, // 0000010000000000 + 0x2800, // 0010100000000000 + 0x1C00, // 0001110000000000 + 0x0000, 0x0000, 0x0000, 0x0000, +}; + +enum CursorStyle { + CURSOR_ARROW = 0, + CURSOR_RESIZE_H, // left-right + CURSOR_RESIZE_V, // up-down + CURSOR_RESIZE_NWSE, // diagonal NW-SE + CURSOR_RESIZE_NESW, // diagonal NE-SW +}; + +// Draw the mouse cursor at (x, y) +inline void draw_cursor(Framebuffer& fb, int x, int y, CursorStyle style = CURSOR_ARROW) { + const uint16_t* outline_data = cursor_outline; + const uint16_t* fill_data = cursor_fill; + int ox = 0, oy = 0; // hotspot offset for centered cursors + + switch (style) { + case CURSOR_RESIZE_H: + outline_data = cursor_h_resize_outline; + fill_data = cursor_h_resize_fill; + ox = -8; oy = -8; + break; + case CURSOR_RESIZE_V: + outline_data = cursor_v_resize_outline; + fill_data = cursor_v_resize_fill; + ox = -8; oy = -8; + break; + case CURSOR_RESIZE_NWSE: + outline_data = cursor_nwse_resize_outline; + fill_data = cursor_nwse_resize_fill; + ox = -8; oy = -8; + break; + case CURSOR_RESIZE_NESW: + outline_data = cursor_nesw_resize_outline; + fill_data = cursor_nesw_resize_fill; + ox = -8; oy = -8; + break; + default: + break; + } + + Color black = colors::BLACK; + Color white = colors::WHITE; + + for (int row = 0; row < 16; row++) { + uint16_t outline = outline_data[row]; + uint16_t fill = fill_data[row]; + for (int col = 0; col < 16; col++) { + uint16_t mask = (uint16_t)(0x8000 >> col); + if (outline & mask) { + fb.put_pixel(x + ox + col, y + oy + row, black); + } else if (fill & mask) { + fb.put_pixel(x + ox + col, y + oy + row, white); + } + } + } +} + +} // namespace gui diff --git a/template/sysroot/include/gui/font.hpp b/template/sysroot/include/gui/font.hpp new file mode 100644 index 0000000..eca26b7 --- /dev/null +++ b/template/sysroot/include/gui/font.hpp @@ -0,0 +1,99 @@ +/* + * font.hpp + * MontaukOS text rendering — TrueType with bitmap fallback + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" +#include "gui/truetype.hpp" + +namespace gui { + +static constexpr int FONT_WIDTH = 8; +static constexpr int FONT_HEIGHT = 16; + +// Defined in font_data.cpp +extern const uint8_t font_data[256 * 16]; + +// Dynamic font height: TTF line height or 16 (bitmap fallback) +inline int system_font_height() { + if (fonts::system_font && fonts::system_font->valid) + return fonts::system_font->get_line_height(fonts::UI_SIZE); + return FONT_HEIGHT; +} + +// Dynamic mono font cell dimensions +inline int mono_cell_width() { + if (fonts::mono && fonts::mono->valid) { + // Monospace: all glyphs have the same advance + GlyphCache* gc = fonts::mono->get_cache(fonts::TERM_SIZE); + CachedGlyph* g = fonts::mono->get_glyph(gc, 'M'); + if (g) return g->advance; + } + return FONT_WIDTH; +} + +inline int mono_cell_height() { + if (fonts::mono && fonts::mono->valid) + return fonts::mono->get_line_height(fonts::TERM_SIZE); + return FONT_HEIGHT; +} + +inline void draw_char(Framebuffer& fb, int x, int y, char c, Color fg) { + const uint8_t* glyph = &font_data[(unsigned char)c * FONT_HEIGHT]; + for (int row = 0; row < FONT_HEIGHT; row++) { + uint8_t bits = glyph[row]; + for (int col = 0; col < FONT_WIDTH; col++) { + if (bits & (0x80 >> col)) { + fb.put_pixel(x + col, y + row, fg); + } + } + } +} + +inline void draw_char_bg(Framebuffer& fb, int x, int y, char c, Color fg, Color bg) { + const uint8_t* glyph = &font_data[(unsigned char)c * FONT_HEIGHT]; + for (int row = 0; row < FONT_HEIGHT; row++) { + uint8_t bits = glyph[row]; + for (int col = 0; col < FONT_WIDTH; col++) { + if (bits & (0x80 >> col)) { + fb.put_pixel(x + col, y + row, fg); + } else { + fb.put_pixel(x + col, y + row, bg); + } + } + } +} + +inline void draw_text(Framebuffer& fb, int x, int y, const char* text, Color fg) { + if (fonts::system_font && fonts::system_font->valid) { + fonts::system_font->draw(fb, x, y, text, fg, fonts::UI_SIZE); + return; + } + for (int i = 0; text[i]; i++) { + draw_char(fb, x + i * FONT_WIDTH, y, text[i], fg); + } +} + +inline void draw_text_bg(Framebuffer& fb, int x, int y, const char* text, Color fg, Color bg) { + if (fonts::system_font && fonts::system_font->valid) { + fonts::system_font->draw_bg(fb, x, y, text, fg, bg, fonts::UI_SIZE); + return; + } + for (int i = 0; text[i]; i++) { + draw_char_bg(fb, x + i * FONT_WIDTH, y, text[i], fg, bg); + } +} + +inline int text_width(const char* text) { + if (fonts::system_font && fonts::system_font->valid) { + return fonts::system_font->measure_text(text, fonts::UI_SIZE); + } + int len = 0; + while (text[len]) len++; + return len * FONT_WIDTH; +} + +} // namespace gui diff --git a/template/sysroot/include/gui/framebuffer.hpp b/template/sysroot/include/gui/framebuffer.hpp new file mode 100644 index 0000000..9a1a4ab --- /dev/null +++ b/template/sysroot/include/gui/framebuffer.hpp @@ -0,0 +1,196 @@ +/* + * framebuffer.hpp + * MontaukOS double-buffered framebuffer abstraction + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include +#include +#include "gui/gui.hpp" + +namespace gui { + +class Framebuffer { + uint32_t* hw_fb; + uint32_t* back_buf; + int fb_width; + int fb_height; + int fb_pitch; // in bytes + +public: + Framebuffer() : hw_fb(nullptr), back_buf(nullptr), fb_width(0), fb_height(0), fb_pitch(0) { + Montauk::FbInfo info; + montauk::fb_info(&info); + + fb_width = (int)info.width; + fb_height = (int)info.height; + fb_pitch = (int)info.pitch; + + hw_fb = (uint32_t*)montauk::fb_map(); + back_buf = (uint32_t*)montauk::alloc((uint64_t)fb_height * fb_pitch); + } + + int width() const { return fb_width; } + int height() const { return fb_height; } + int pitch() const { return fb_pitch; } + + uint32_t* buffer() { return back_buf; } + + inline void put_pixel(int x, int y, Color c) { + if (x < 0 || x >= fb_width || y < 0 || y >= fb_height) return; + uint32_t* row = (uint32_t*)((uint8_t*)back_buf + y * fb_pitch); + row[x] = c.to_pixel(); + } + + inline void put_pixel_alpha(int x, int y, Color c) { + if (x < 0 || x >= fb_width || y < 0 || y >= fb_height) return; + if (c.a == 0) return; + if (c.a == 255) { + put_pixel(x, y, c); + return; + } + + uint32_t* row = (uint32_t*)((uint8_t*)back_buf + y * fb_pitch); + uint32_t dst = row[x]; + + uint8_t dr = (dst >> 16) & 0xFF; + uint8_t dg = (dst >> 8) & 0xFF; + uint8_t db = dst & 0xFF; + + uint32_t a = c.a; + uint32_t inv_a = 255 - a; + + // Fast alpha blend: out = (src * alpha + dst * (255 - alpha) + 128) / 255 + // Approximation: (x + 1 + (x >> 8)) >> 8 for division by 255 + uint32_t rr = a * c.r + inv_a * dr; + uint32_t gg = a * c.g + inv_a * dg; + uint32_t bb = a * c.b + inv_a * db; + + rr = (rr + 1 + (rr >> 8)) >> 8; + gg = (gg + 1 + (gg >> 8)) >> 8; + bb = (bb + 1 + (bb >> 8)) >> 8; + + row[x] = (0xFF000000) | (rr << 16) | (gg << 8) | bb; + } + + inline void fill_rect(int x, int y, int w, int h, Color c) { + // Clip to screen bounds + int x0 = x < 0 ? 0 : x; + int y0 = y < 0 ? 0 : y; + int x1 = (x + w) > fb_width ? fb_width : (x + w); + int y1 = (y + h) > fb_height ? fb_height : (y + h); + + if (x0 >= x1 || y0 >= y1) return; + + uint32_t pixel = c.to_pixel(); + int clipped_w = x1 - x0; + + for (int row = y0; row < y1; row++) { + uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + row * fb_pitch) + x0; + for (int col = 0; col < clipped_w; col++) { + dst[col] = pixel; + } + } + } + + inline void fill_rect_alpha(int x, int y, int w, int h, Color c) { + if (c.a == 0) return; + if (c.a == 255) { + fill_rect(x, y, w, h, c); + return; + } + + int x0 = x < 0 ? 0 : x; + int y0 = y < 0 ? 0 : y; + int x1 = (x + w) > fb_width ? fb_width : (x + w); + int y1 = (y + h) > fb_height ? fb_height : (y + h); + + if (x0 >= x1 || y0 >= y1) return; + + uint32_t a = c.a; + uint32_t inv_a = 255 - a; + uint32_t src_r = a * c.r; + uint32_t src_g = a * c.g; + uint32_t src_b = a * c.b; + + for (int row = y0; row < y1; row++) { + uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + row * fb_pitch) + x0; + for (int col = 0; col < x1 - x0; col++) { + uint32_t d = dst[col]; + uint32_t dr = (d >> 16) & 0xFF; + uint32_t dg = (d >> 8) & 0xFF; + uint32_t db = d & 0xFF; + + uint32_t rr = src_r + inv_a * dr; + uint32_t gg = src_g + inv_a * dg; + uint32_t bb = src_b + inv_a * db; + + rr = (rr + 1 + (rr >> 8)) >> 8; + gg = (gg + 1 + (gg >> 8)) >> 8; + bb = (bb + 1 + (bb >> 8)) >> 8; + + dst[col] = (0xFF000000) | (rr << 16) | (gg << 8) | bb; + } + } + } + + inline void blit(int x, int y, int w, int h, const uint32_t* pixels) { + for (int row = 0; row < h; row++) { + int dy = y + row; + if (dy < 0 || dy >= fb_height) continue; + for (int col = 0; col < w; col++) { + int dx = x + col; + if (dx < 0 || dx >= fb_width) continue; + uint32_t* dst_row = (uint32_t*)((uint8_t*)back_buf + dy * fb_pitch); + dst_row[dx] = pixels[row * w + col]; + } + } + } + + inline void blit_alpha(int x, int y, int w, int h, const uint32_t* pixels) { + for (int row = 0; row < h; row++) { + int dy = y + row; + if (dy < 0 || dy >= fb_height) continue; + for (int col = 0; col < w; col++) { + int dx = x + col; + if (dx < 0 || dx >= fb_width) continue; + + uint32_t src = pixels[row * w + col]; + uint8_t sa = (src >> 24) & 0xFF; + if (sa == 0) continue; + + uint8_t sr = (src >> 16) & 0xFF; + uint8_t sg = (src >> 8) & 0xFF; + uint8_t sb = src & 0xFF; + + if (sa == 255) { + uint32_t* dst_row = (uint32_t*)((uint8_t*)back_buf + dy * fb_pitch); + dst_row[dx] = src; + continue; + } + + Color sc = {sr, sg, sb, sa}; + put_pixel_alpha(dx, dy, sc); + } + } + } + + inline void clear(Color c) { + fill_rect(0, 0, fb_width, fb_height, c); + } + + inline void flip() { + // Copy back buffer to hardware framebuffer, row by row (pitch may differ) + int row_pixels = fb_width; + for (int y = 0; y < fb_height; y++) { + uint32_t* src = (uint32_t*)((uint8_t*)back_buf + y * fb_pitch); + uint32_t* dst = (uint32_t*)((uint8_t*)hw_fb + y * fb_pitch); + for (int x = 0; x < row_pixels; x++) { + dst[x] = src[x]; + } + } + } +}; + +} // namespace gui diff --git a/template/sysroot/include/gui/gui.hpp b/template/sysroot/include/gui/gui.hpp new file mode 100644 index 0000000..becfab6 --- /dev/null +++ b/template/sysroot/include/gui/gui.hpp @@ -0,0 +1,94 @@ +/* + * gui.hpp + * MontaukOS core GUI types and utilities + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include + +namespace gui { + +// 16.16 fixed-point type +using fixed_t = int32_t; + +static constexpr int FIXED_SHIFT = 16; + +inline fixed_t int_to_fixed(int v) { return v << FIXED_SHIFT; } +inline int fixed_to_int(fixed_t v) { return v >> FIXED_SHIFT; } +inline fixed_t fixed_mul(fixed_t a, fixed_t b) { return (int32_t)(((int64_t)a * b) >> FIXED_SHIFT); } +inline fixed_t fixed_div(fixed_t a, fixed_t b) { return (int32_t)(((int64_t)a << FIXED_SHIFT) / b); } +inline fixed_t fixed_from_parts(int whole, int frac_num, int frac_den) { + return int_to_fixed(whole) + (int32_t)(((int64_t)frac_num << FIXED_SHIFT) / frac_den); +} + +struct Color { + uint8_t r, g, b, a; + + static constexpr Color from_rgb(uint8_t r, uint8_t g, uint8_t b) { return {r, g, b, 255}; } + static constexpr Color from_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return {r, g, b, a}; } + static constexpr Color from_hex(uint32_t hex) { + return {(uint8_t)((hex >> 16) & 0xFF), (uint8_t)((hex >> 8) & 0xFF), (uint8_t)(hex & 0xFF), 255}; + } + + constexpr uint32_t to_pixel() const { return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; } +}; + +// Named colors for the desktop theme +namespace colors { + static constexpr Color DESKTOP_BG = {0xE0, 0xE0, 0xE0, 0xFF}; + static constexpr Color PANEL_BG = {0x2B, 0x3E, 0x50, 0xFF}; + static constexpr Color TITLEBAR_BG = {0xF5, 0xF5, 0xF5, 0xFF}; + static constexpr Color WINDOW_BG = {0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr Color BORDER = {0xCC, 0xCC, 0xCC, 0xFF}; + static constexpr Color TEXT_COLOR = {0x33, 0x33, 0x33, 0xFF}; + static constexpr Color PANEL_TEXT = {0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr Color ACCENT = {0x36, 0x7B, 0xF0, 0xFF}; + static constexpr Color CLOSE_BTN = {0xFF, 0x5F, 0x57, 0xFF}; + static constexpr Color MAX_BTN = {0x28, 0xCA, 0x42, 0xFF}; + static constexpr Color MIN_BTN = {0xFF, 0xBD, 0x2E, 0xFF}; + static constexpr Color SHADOW = {0x00, 0x00, 0x00, 0x40}; + static constexpr Color TRANSPARENT = {0x00, 0x00, 0x00, 0x00}; + static constexpr Color BLACK = {0x00, 0x00, 0x00, 0xFF}; + static constexpr Color WHITE = {0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr Color ICON_COLOR = {0x5C, 0x61, 0x6C, 0xFF}; + static constexpr Color SCROLLBAR_BG = {0xF0, 0xF0, 0xF0, 0xFF}; + static constexpr Color SCROLLBAR_FG = {0xC0, 0xC0, 0xC0, 0xFF}; + static constexpr Color MENU_BG = {0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr Color MENU_HOVER = {0xE8, 0xF0, 0xFE, 0xFF}; + static constexpr Color TERM_BG = {0x2D, 0x2D, 0x2D, 0xFF}; + static constexpr Color TERM_FG = {0xCC, 0xCC, 0xCC, 0xFF}; + static constexpr Color PANEL_INDICATOR_ACTIVE = {0x45, 0x58, 0x6A, 0xFF}; + static constexpr Color PANEL_INDICATOR_INACTIVE = {0x35, 0x48, 0x5A, 0xFF}; +} + +struct Point { + int x, y; +}; + +struct Rect { + int x, y, w, h; + + bool contains(int px, int py) const { + return px >= x && px < x + w && py >= y && py < y + h; + } + + Rect intersect(const Rect& other) const { + int rx = x > other.x ? x : other.x; + int ry = y > other.y ? y : other.y; + int rx2 = (x + w) < (other.x + other.w) ? (x + w) : (other.x + other.w); + int ry2 = (y + h) < (other.y + other.h) ? (y + h) : (other.y + other.h); + if (rx2 <= rx || ry2 <= ry) return {0, 0, 0, 0}; + return {rx, ry, rx2 - rx, ry2 - ry}; + } + + bool empty() const { return w <= 0 || h <= 0; } +}; + +// Simple inline utility functions +inline int gui_min(int a, int b) { return a < b ? a : b; } +inline int gui_max(int a, int b) { return a > b ? a : b; } +inline int gui_abs(int a) { return a < 0 ? -a : a; } +inline int gui_clamp(int v, int lo, int hi) { return v < lo ? lo : (v > hi ? hi : v); } + +} // namespace gui diff --git a/template/sysroot/include/gui/stb_image.h b/template/sysroot/include/gui/stb_image.h new file mode 100644 index 0000000..9eedabe --- /dev/null +++ b/template/sysroot/include/gui/stb_image.h @@ -0,0 +1,7988 @@ +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + int hit_zeof_once; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); + } + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (len > a->zout_end - zout) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + a->hit_zeof_once = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub +}; + +static int stbi__paeth(int a, int b, int c) +{ + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16 ? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + + for (j=0; j < y; ++j) { + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; + int filter = *raw++; + + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; + } + + raw += nk; + + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; + + // expand bits to bytes first + if (depth == 4) { + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; + } + } else if (depth == 2) { + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; + } + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; + } + } + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); + if (img_n == 1) { + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; + } + } else { + STBI_ASSERT(img_n == 3); + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; + } + } + } + } + } + + STBI_FREE(filter_buf); + if (!all_ok) return 0; + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/template/sysroot/include/gui/stb_math.h b/template/sysroot/include/gui/stb_math.h new file mode 100644 index 0000000..07875b2 --- /dev/null +++ b/template/sysroot/include/gui/stb_math.h @@ -0,0 +1,95 @@ +/* + * stb_math.h + * Math functions for stb_truetype in freestanding environment + * Copyright (c) 2026 Daniel Hammer +*/ + +#ifndef STB_MATH_H +#define STB_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +static inline double stb_floor(double x) { + double i = (double)(long long)x; + return (x < i) ? i - 1.0 : i; +} + +static inline double stb_ceil(double x) { + double f = stb_floor(x); + return (x > f) ? f + 1.0 : f; +} + +static inline double stb_fabs(double x) { + return x < 0.0 ? -x : x; +} + +static inline double stb_fmod(double x, double y) { + if (y == 0.0) return 0.0; + return x - (double)((long long)(x / y)) * y; +} + +static inline double stb_sqrt(double x) { + if (x <= 0.0) return 0.0; + double guess = x; + for (int i = 0; i < 30; i++) + guess = (guess + x / guess) * 0.5; + return guess; +} + +static inline double stb_pow(double base, double exp) { + if (exp == 0.0) return 1.0; + if (exp == 1.0) return base; + if (base == 0.0) return 0.0; + // Integer exponent fast path + if (exp == (double)(long long)exp) { + long long e = (long long)exp; + int neg = 0; + if (e < 0) { neg = 1; e = -e; } + double r = 1.0; + double b = base; + while (e > 0) { + if (e & 1) r *= b; + b *= b; + e >>= 1; + } + return neg ? 1.0 / r : r; + } + return 0.0; +} + +static inline double stb_cos(double x) { + // Reduce to [0, 2*pi] + const double PI = 3.14159265358979323846; + const double TWO_PI = 6.28318530717958647692; + x = stb_fmod(stb_fabs(x), TWO_PI); + // Taylor series: cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ... + double x2 = x * x; + double term = 1.0; + double result = 1.0; + for (int i = 1; i <= 10; i++) { + term *= -x2 / (double)((2 * i - 1) * (2 * i)); + result += term; + } + return result; +} + +static inline double stb_acos(double x) { + // Clamp input + if (x <= -1.0) return 3.14159265358979323846; + if (x >= 1.0) return 0.0; + // Polynomial approximation (Abramowitz & Stegun style) + double ax = stb_fabs(x); + double result = (-0.0187293 * ax + 0.0742610) * ax - 0.2121144; + result = (result * ax + 1.5707288) * stb_sqrt(1.0 - ax); + if (x < 0.0) + return 3.14159265358979323846 - result; + return result; +} + +#ifdef __cplusplus +} +#endif + +#endif // STB_MATH_H diff --git a/template/sysroot/include/gui/stb_truetype.h b/template/sysroot/include/gui/stb_truetype.h new file mode 100644 index 0000000..d3d1faa --- /dev/null +++ b/template/sysroot/include/gui/stb_truetype.h @@ -0,0 +1,5084 @@ +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) Yakov Galka +// +// VERSION HISTORY +// +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + case STBTT_PLATFORM_ID_MAC: + // Accept Mac Roman as fallback (common in PDF subset fonts) + if (info->index_map == 0) + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start, last; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = (sy1 - sy0) * e->direction; + STBTT_assert(x >= 0 && x < len); + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, y_final, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; + + sign = e->direction; + + // area of the rectangle covered from sy0..y_crossing + area = sign * (y_crossing-sy0); + + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 + area += step; + } + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); + + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + + // the rest of the line is filled based on the total height of the line segment in this pixel + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + // distance from singular values (in the same units as the pixel grid) + const float eps = 1./1024, eps2 = eps*eps; + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 >= eps2) + precompute[i] = 1.0f / len2; + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear + if (STBTT_fabs(b) >= eps2) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/template/sysroot/include/gui/svg.hpp b/template/sysroot/include/gui/svg.hpp new file mode 100644 index 0000000..5b821cf --- /dev/null +++ b/template/sysroot/include/gui/svg.hpp @@ -0,0 +1,1521 @@ +/* + * svg.hpp + * MontaukOS SVG icon parser and scanline rasterizer + * Handles the Flat-Remix symbolic icon subset (path, circle, rect) + * All math uses 16.16 fixed-point -- NO floating point. + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include + +namespace gui { + +// --------------------------------------------------------------------------- +// SVG icon result +// --------------------------------------------------------------------------- +struct SvgIcon { + uint32_t* pixels; // ARGB pixel data (heap-allocated) + int width; + int height; +}; + +// --------------------------------------------------------------------------- +// Edge used by the scanline rasterizer +// --------------------------------------------------------------------------- +struct SvgEdge { + fixed_t x0, y0, x1, y1; +}; + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- +static constexpr int SVG_MAX_EDGES = 8192; +static constexpr int SVG_MAX_PATH_LEN = 8192; +static constexpr int SVG_MAX_FILE_SIZE = 32768; +static constexpr int SVG_BEZIER_STEPS = 8; +static constexpr int SVG_MAX_GRADIENTS = 8; + +// Gradient color table — stores first stop color for url(#id) resolution +struct SvgGradient { + char id[32]; + Color color; // first stop-color +}; + +struct SvgGradientTable { + SvgGradient entries[SVG_MAX_GRADIENTS]; + int count; + + void clear() { count = 0; } + + void add(const char* id, Color c) { + if (count >= SVG_MAX_GRADIENTS) return; + int i = 0; + while (id[i] && i < 31) { entries[count].id[i] = id[i]; i++; } + entries[count].id[i] = '\0'; + entries[count].color = c; + count++; + } + + // Look up gradient by id. Returns true if found. + bool lookup(const char* id, Color* out) const { + for (int i = 0; i < count; i++) { + const char* a = entries[i].id; + const char* b = id; + bool match = true; + while (*a && *b) { + if (*a != *b) { match = false; break; } + a++; b++; + } + if (match && *a == '\0' && *b == '\0') { + *out = entries[i].color; + return true; + } + } + return false; + } +}; + +// --------------------------------------------------------------------------- +// CSS class color table (.ClassName { color: #rrggbb; }) +// Used to resolve fill:currentColor via the element's class= attribute. +// --------------------------------------------------------------------------- +static constexpr int SVG_MAX_CSS_CLASSES = 8; + +struct SvgCssClass { + char name[48]; + Color color; +}; + +struct SvgCssTable { + SvgCssClass entries[SVG_MAX_CSS_CLASSES]; + int count; + + void clear() { count = 0; } + + void add(const char* name, Color c) { + if (count >= SVG_MAX_CSS_CLASSES) return; + int i = 0; + while (name[i] && i < 47) { entries[count].name[i] = name[i]; i++; } + entries[count].name[i] = '\0'; + entries[count].color = c; + count++; + } + + // Look up class by name (first token if multiple classes are listed). + // Returns true if found. + bool lookup(const char* cls, Color* out) const { + for (int i = 0; i < count; i++) { + const char* a = entries[i].name; + const char* b = cls; + bool match = true; + while (*a && *b) { + if (*a != *b) { match = false; break; } + a++; b++; + } + if (match && *a == '\0' && (*b == '\0' || *b == ' ')) { + *out = entries[i].color; + return true; + } + } + return false; + } +}; + +// --------------------------------------------------------------------------- +// Fixed-point number parser (NO floating point) +// Parses strings like "3.25", "-0.5", ".1115", "16" +// Returns the number of characters consumed. +// --------------------------------------------------------------------------- +inline int svg_parse_fixed(const char* s, fixed_t* out) { + const char* p = s; + bool neg = false; + + if (*p == '-') { neg = true; ++p; } + else if (*p == '+') { ++p; } + + // Integer part + int32_t integer = 0; + while (*p >= '0' && *p <= '9') { + integer = integer * 10 + (*p - '0'); + ++p; + } + + // Fractional part + int32_t frac = 0; + int32_t frac_div = 1; + if (*p == '.') { + ++p; + while (*p >= '0' && *p <= '9') { + if (frac_div < 100000) { // prevent overflow + frac = frac * 10 + (*p - '0'); + frac_div *= 10; + } + ++p; + } + } + + fixed_t val = int_to_fixed(integer); + if (frac_div > 1) { + val += (int32_t)(((int64_t)frac << 16) / frac_div); + } + + // Scientific notation (e.g. 2e-3, 7e-3) + if (*p == 'e' || *p == 'E') { + ++p; + bool exp_neg = false; + if (*p == '-') { exp_neg = true; ++p; } + else if (*p == '+') { ++p; } + int exp_val = 0; + while (*p >= '0' && *p <= '9') { + exp_val = exp_val * 10 + (*p - '0'); + ++p; + } + for (int i = 0; i < exp_val; i++) { + if (exp_neg) val /= 10; + else val *= 10; + } + } + + if (neg) val = -val; + *out = val; + return (int)(p - s); +} + +// --------------------------------------------------------------------------- +// String helpers (no stdlib) +// --------------------------------------------------------------------------- +inline bool svg_char_is_ws(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; +} + +inline bool svg_char_is_sep(char c) { + return svg_char_is_ws(c) || c == ','; +} + +inline bool svg_char_is_num_start(char c) { + return (c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.'; +} + +inline bool svg_char_is_cmd(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +inline int svg_strlen(const char* s) { + int n = 0; + while (s[n]) ++n; + return n; +} + +inline bool svg_strncmp(const char* a, const char* b, int n) { + for (int i = 0; i < n; ++i) + if (a[i] != b[i]) return false; + return true; +} + +inline void svg_memset(void* dst, uint8_t val, int n) { + auto* d = (uint8_t*)dst; + for (int i = 0; i < n; ++i) d[i] = val; +} + +inline void svg_memcpy(void* dst, const void* src, int n) { + auto* d = (uint8_t*)dst; + auto* s = (const uint8_t*)src; + for (int i = 0; i < n; ++i) d[i] = s[i]; +} + +// --------------------------------------------------------------------------- +// Mini XML attribute extraction +// --------------------------------------------------------------------------- + +// Find the next occurrence of needle in haystack (haystack has length hLen). +// Returns pointer to start of match, or nullptr. +inline const char* svg_strstr(const char* haystack, int hLen, const char* needle) { + int nLen = svg_strlen(needle); + if (nLen == 0 || nLen > hLen) return nullptr; + for (int i = 0; i <= hLen - nLen; ++i) { + if (svg_strncmp(haystack + i, needle, nLen)) + return haystack + i; + } + return nullptr; +} + +// Check if a character can be part of an XML attribute name +inline bool svg_char_is_attrname(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '-' || c == '_' || c == ':'; +} + +// Extract the value of an XML attribute: attr="value" +// The attr string should include a leading space (e.g., " cx") to distinguish +// from substrings of other attribute names. +// Writes into buf (up to maxLen-1 chars), returns length or -1 if not found. +inline int svg_get_attr(const char* tag, int tagLen, const char* attr, char* buf, int maxLen) { + int attrLen = svg_strlen(attr); + const char* search_start = tag; + int search_len = tagLen; + + while (search_len > 0) { + const char* p = svg_strstr(search_start, search_len, attr); + if (!p) return -1; + + // Ensure this is the exact attribute name, not a prefix of another + // (e.g., " r" should not match " rx" or " ry") + const char* after_name = p + attrLen; + if (after_name < tag + tagLen && svg_char_is_attrname(*after_name)) { + // This is a prefix of a longer attribute name, skip and search again + search_start = after_name; + search_len = tagLen - (int)(search_start - tag); + continue; + } + + p = after_name; + // skip whitespace around '=' + while (p < tag + tagLen && svg_char_is_ws(*p)) ++p; + if (p >= tag + tagLen || *p != '=') return -1; + ++p; + while (p < tag + tagLen && svg_char_is_ws(*p)) ++p; + if (p >= tag + tagLen) return -1; + char quote = *p; + if (quote != '"' && quote != '\'') return -1; + ++p; + int len = 0; + while (p < tag + tagLen && *p != quote && len < maxLen - 1) { + buf[len++] = *p++; + } + buf[len] = '\0'; + return len; + } + return -1; +} + +// Parse an integer from a string (no sign, simple decimal). +inline int svg_parse_int(const char* s) { + int v = 0; + while (*s >= '0' && *s <= '9') { + v = v * 10 + (*s - '0'); + ++s; + } + return v; +} + +// Parse a hex color like "#5c616c" or "#fff" into a Color. +inline Color svg_parse_hex_color(const char* s) { + if (*s == '#') ++s; + auto hexval = [](char c) -> uint8_t { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); + if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); + return 0; + }; + // Count hex digits + int len = 0; + for (const char* p = s; *p; ++p) { + if ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) + ++len; + else break; + } + if (len == 3) { + // 3-digit shorthand: #rgb → #rrggbb + uint8_t r = hexval(s[0]); r = (r << 4) | r; + uint8_t g = hexval(s[1]); g = (g << 4) | g; + uint8_t b = hexval(s[2]); b = (b << 4) | b; + return Color::from_rgb(r, g, b); + } + uint8_t r = (hexval(s[0]) << 4) | hexval(s[1]); + uint8_t g = (hexval(s[2]) << 4) | hexval(s[3]); + uint8_t b = (hexval(s[4]) << 4) | hexval(s[5]); + return Color::from_rgb(r, g, b); +} + +// --------------------------------------------------------------------------- +// Edge list builder +// --------------------------------------------------------------------------- +struct SvgEdgeList { + SvgEdge* edges; + int count; + int capacity; + + void init(int cap) { + edges = (SvgEdge*)montauk::malloc(cap * sizeof(SvgEdge)); + count = 0; + capacity = cap; + } + + void clear() { count = 0; } + + void add(fixed_t x0, fixed_t y0, fixed_t x1, fixed_t y1) { + if (count >= capacity) return; + // skip horizontal edges (they don't contribute to scanline crossings) + if (y0 == y1) return; + edges[count++] = {x0, y0, x1, y1}; + } +}; + +// --------------------------------------------------------------------------- +// Bezier flattening (fixed-point) +// --------------------------------------------------------------------------- + +// Cubic bezier: add line segments approximating B(t) for t in [0,1] +inline void svg_flatten_cubic(SvgEdgeList& el, + fixed_t x0, fixed_t y0, + fixed_t x1, fixed_t y1, + fixed_t x2, fixed_t y2, + fixed_t x3, fixed_t y3) { + constexpr int N = SVG_BEZIER_STEPS; + fixed_t px = x0, py = y0; + for (int i = 1; i <= N; ++i) { + // t = i/N in 16.16: (i << 16) / N + fixed_t t = (int32_t)(((int64_t)i << 16) / N); + fixed_t omt = int_to_fixed(1) - t; // 1 - t + + // (1-t)^2 and t^2 + fixed_t omt2 = fixed_mul(omt, omt); + fixed_t t2 = fixed_mul(t, t); + + // (1-t)^3 and t^3 + fixed_t omt3 = fixed_mul(omt2, omt); + fixed_t t3 = fixed_mul(t2, t); + + // 3*(1-t)^2*t and 3*(1-t)*t^2 + fixed_t c1 = fixed_mul(omt2, t) * 3; + fixed_t c2 = fixed_mul(omt, t2) * 3; + + fixed_t nx = fixed_mul(omt3, x0) + fixed_mul(c1, x1) + fixed_mul(c2, x2) + fixed_mul(t3, x3); + fixed_t ny = fixed_mul(omt3, y0) + fixed_mul(c1, y1) + fixed_mul(c2, y2) + fixed_mul(t3, y3); + + el.add(px, py, nx, ny); + px = nx; + py = ny; + } +} + +// Quadratic bezier: add line segments approximating B(t) for t in [0,1] +inline void svg_flatten_quad(SvgEdgeList& el, + fixed_t x0, fixed_t y0, + fixed_t x1, fixed_t y1, + fixed_t x2, fixed_t y2) { + constexpr int N = SVG_BEZIER_STEPS; + fixed_t px = x0, py = y0; + for (int i = 1; i <= N; ++i) { + fixed_t t = (int32_t)(((int64_t)i << 16) / N); + fixed_t omt = int_to_fixed(1) - t; + + // (1-t)^2*P0 + 2*(1-t)*t*P1 + t^2*P2 + fixed_t omt2 = fixed_mul(omt, omt); + fixed_t t2 = fixed_mul(t, t); + fixed_t c1 = fixed_mul(omt, t) * 2; + + fixed_t nx = fixed_mul(omt2, x0) + fixed_mul(c1, x1) + fixed_mul(t2, x2); + fixed_t ny = fixed_mul(omt2, y0) + fixed_mul(c1, y1) + fixed_mul(t2, y2); + + el.add(px, py, nx, ny); + px = nx; + py = ny; + } +} + +// --------------------------------------------------------------------------- +// Circle to edges: approximate a circle as N line segments +// --------------------------------------------------------------------------- +inline void svg_circle_edges(SvgEdgeList& el, fixed_t cx, fixed_t cy, fixed_t r) { + // Approximate circle with 16 segments using a precomputed sin/cos table + // for angles 0, 22.5, 45, ... 337.5 degrees. + // sin/cos in 16.16 fixed-point for 16 evenly-spaced angles: + static const fixed_t cos16[16] = { + 65536, 60547, 46341, 25080, 0, -25080, -46341, -60547, + -65536, -60547, -46341, -25080, 0, 25080, 46341, 60547 + }; + static const fixed_t sin16[16] = { + 0, 25080, 46341, 60547, 65536, 60547, 46341, 25080, + 0, -25080, -46341, -60547, -65536, -60547, -46341, -25080 + }; + + fixed_t px = cx + fixed_mul(r, cos16[0]); + fixed_t py = cy + fixed_mul(r, sin16[0]); + for (int i = 1; i <= 16; ++i) { + int idx = i & 15; + fixed_t nx = cx + fixed_mul(r, cos16[idx]); + fixed_t ny = cy + fixed_mul(r, sin16[idx]); + el.add(px, py, nx, ny); + px = nx; + py = ny; + } +} + +// --------------------------------------------------------------------------- +// Rounded rect to edges +// --------------------------------------------------------------------------- +inline void svg_rect_edges(SvgEdgeList& el, fixed_t x, fixed_t y, fixed_t w, fixed_t h, + fixed_t rx, fixed_t ry) { + if (rx <= 0 && ry <= 0) { + // Simple rectangle: 4 edges + fixed_t x2 = x + w; + fixed_t y2 = y + h; + el.add(x, y, x2, y); // top + el.add(x2, y, x2, y2); // right + el.add(x2, y2, x, y2); // bottom + el.add(x, y2, x, y); // left + return; + } + + // Clamp radii + fixed_t half_w = w >> 1; + fixed_t half_h = h >> 1; + if (rx > half_w) rx = half_w; + if (ry > half_h) ry = half_h; + + // Quarter-circle corner with 4 segments per corner. + // cos/sin for 0, 22.5, 45, 67.5, 90 degrees (5 points, 4 segments): + static const fixed_t qcos[5] = { 65536, 60547, 46341, 25080, 0 }; + static const fixed_t qsin[5] = { 0, 25080, 46341, 60547, 65536 }; + + // Corners: top-right, bottom-right, bottom-left, top-left + // Each corner has a center and a quadrant direction for cos/sin application + struct Corner { fixed_t cx, cy; int sx, sy; }; + Corner corners[4] = { + { x + w - rx, y + ry, 1, -1 }, // top-right + { x + w - rx, y + h - ry, 1, 1 }, // bottom-right + { x + rx, y + h - ry, -1, 1 }, // bottom-left + { x + rx, y + ry, -1, -1 }, // top-left + }; + + for (int c = 0; c < 4; ++c) { + Corner& cn = corners[c]; + fixed_t px = cn.cx + fixed_mul(rx, qcos[0]) * cn.sx; + fixed_t py = cn.cy + fixed_mul(ry, qsin[0]) * cn.sy; + for (int i = 1; i <= 4; ++i) { + fixed_t nx = cn.cx + fixed_mul(rx, qcos[i]) * cn.sx; + fixed_t ny = cn.cy + fixed_mul(ry, qsin[i]) * cn.sy; + el.add(px, py, nx, ny); + px = nx; + py = ny; + } + } + + // Straight edges between corners + // Top edge: top-left corner end -> top-right corner start + el.add(x + rx, y, x + w - rx, y); + // Right edge: top-right corner end -> bottom-right corner start + el.add(x + w, y + ry, x + w, y + h - ry); + // Bottom edge: bottom-right corner end -> bottom-left corner start + el.add(x + w - rx, y + h, x + rx, y + h); + // Left edge: bottom-left corner end -> top-left corner start + el.add(x, y + h - ry, x, y + ry); +} + +// --------------------------------------------------------------------------- +// Path command parser: tokenize the 'd' attribute +// --------------------------------------------------------------------------- +struct SvgPathParser { + const char* data; + int len; + int pos; + + void init(const char* d, int l) { data = d; len = l; pos = 0; } + + void skip_separators() { + while (pos < len && svg_char_is_sep(data[pos])) ++pos; + } + + bool has_more() const { return pos < len; } + + // Peek at what's next: command letter, number, or end + bool next_is_number() { + skip_separators(); + if (pos >= len) return false; + return svg_char_is_num_start(data[pos]); + } + + char read_command() { + skip_separators(); + if (pos >= len) return '\0'; + if (svg_char_is_cmd(data[pos]) && data[pos] != 'e' && data[pos] != 'E') { + return data[pos++]; + } + return '\0'; + } + + fixed_t read_number() { + skip_separators(); + if (pos >= len) return 0; + fixed_t val = 0; + int consumed = svg_parse_fixed(data + pos, &val); + pos += consumed; + return val; + } +}; + +// --------------------------------------------------------------------------- +// Process an SVG path 'd' attribute into edges +// --------------------------------------------------------------------------- +inline void svg_path_to_edges(SvgEdgeList& el, const char* d, int dLen, + fixed_t scale_x, fixed_t scale_y, + fixed_t off_x, fixed_t off_y) { + SvgPathParser pp; + pp.init(d, dLen); + + fixed_t cur_x = 0, cur_y = 0; // current point + fixed_t start_x = 0, start_y = 0; // subpath start + fixed_t last_cx = 0, last_cy = 0; // last control point (for S/T) + char last_cmd = '\0'; + + auto scale_pt = [&](fixed_t x, fixed_t y, fixed_t* ox, fixed_t* oy) { + *ox = fixed_mul(x - off_x, scale_x); + *oy = fixed_mul(y - off_y, scale_y); + }; + + while (pp.has_more()) { + char cmd = '\0'; + + // Try reading a command letter + pp.skip_separators(); + if (pp.pos < pp.len && svg_char_is_cmd(pp.data[pp.pos]) && + pp.data[pp.pos] != 'e' && pp.data[pp.pos] != 'E') { + cmd = pp.data[pp.pos++]; + } else if (pp.next_is_number()) { + // Implicit repeat of last command + // After M, implicit repeat is L; after m, implicit repeat is l + if (last_cmd == 'M') cmd = 'L'; + else if (last_cmd == 'm') cmd = 'l'; + else cmd = last_cmd; + } else { + // Skip unknown character + if (pp.pos < pp.len) pp.pos++; + continue; + } + + if (cmd == '\0') break; + + switch (cmd) { + case 'M': { + fixed_t x = pp.read_number(); + fixed_t y = pp.read_number(); + cur_x = x; cur_y = y; + start_x = x; start_y = y; + last_cmd = 'M'; + break; + } + case 'm': { + fixed_t dx = pp.read_number(); + fixed_t dy = pp.read_number(); + cur_x += dx; cur_y += dy; + start_x = cur_x; start_y = cur_y; + last_cmd = 'm'; + break; + } + case 'L': { + fixed_t x = pp.read_number(); + fixed_t y = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x, y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_x = x; cur_y = y; + last_cmd = 'L'; + break; + } + case 'l': { + fixed_t dx = pp.read_number(); + fixed_t dy = pp.read_number(); + fixed_t nx = cur_x + dx, ny = cur_y + dy; + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(nx, ny, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_x = nx; cur_y = ny; + last_cmd = 'l'; + break; + } + case 'H': { + fixed_t x = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x, cur_y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_x = x; + last_cmd = 'H'; + break; + } + case 'h': { + fixed_t dx = pp.read_number(); + fixed_t nx = cur_x + dx; + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(nx, cur_y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_x = nx; + last_cmd = 'h'; + break; + } + case 'V': { + fixed_t y = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(cur_x, y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_y = y; + last_cmd = 'V'; + break; + } + case 'v': { + fixed_t dy = pp.read_number(); + fixed_t ny = cur_y + dy; + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(cur_x, ny, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_y = ny; + last_cmd = 'v'; + break; + } + case 'C': { + fixed_t x1 = pp.read_number(), y1 = pp.read_number(); + fixed_t x2 = pp.read_number(), y2 = pp.read_number(); + fixed_t x3 = pp.read_number(), y3 = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x1, y1, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + scale_pt(x3, y3, &sx3, &sy3); + svg_flatten_cubic(el, sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3); + last_cx = x2; last_cy = y2; + cur_x = x3; cur_y = y3; + last_cmd = 'C'; + break; + } + case 'c': { + fixed_t dx1 = pp.read_number(), dy1 = pp.read_number(); + fixed_t dx2 = pp.read_number(), dy2 = pp.read_number(); + fixed_t dx3 = pp.read_number(), dy3 = pp.read_number(); + fixed_t x1 = cur_x + dx1, y1 = cur_y + dy1; + fixed_t x2 = cur_x + dx2, y2 = cur_y + dy2; + fixed_t x3 = cur_x + dx3, y3 = cur_y + dy3; + fixed_t sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x1, y1, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + scale_pt(x3, y3, &sx3, &sy3); + svg_flatten_cubic(el, sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3); + last_cx = x2; last_cy = y2; + cur_x = x3; cur_y = y3; + last_cmd = 'c'; + break; + } + case 'S': { + // Smooth cubic: reflect last control point + fixed_t rcx = cur_x * 2 - last_cx; + fixed_t rcy = cur_y * 2 - last_cy; + if (last_cmd != 'C' && last_cmd != 'c' && last_cmd != 'S' && last_cmd != 's') { + rcx = cur_x; rcy = cur_y; + } + fixed_t x2 = pp.read_number(), y2 = pp.read_number(); + fixed_t x3 = pp.read_number(), y3 = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(rcx, rcy, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + scale_pt(x3, y3, &sx3, &sy3); + svg_flatten_cubic(el, sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3); + last_cx = x2; last_cy = y2; + cur_x = x3; cur_y = y3; + last_cmd = 'S'; + break; + } + case 's': { + fixed_t rcx = cur_x * 2 - last_cx; + fixed_t rcy = cur_y * 2 - last_cy; + if (last_cmd != 'C' && last_cmd != 'c' && last_cmd != 'S' && last_cmd != 's') { + rcx = cur_x; rcy = cur_y; + } + fixed_t dx2 = pp.read_number(), dy2 = pp.read_number(); + fixed_t dx3 = pp.read_number(), dy3 = pp.read_number(); + fixed_t x2 = cur_x + dx2, y2 = cur_y + dy2; + fixed_t x3 = cur_x + dx3, y3 = cur_y + dy3; + fixed_t sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(rcx, rcy, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + scale_pt(x3, y3, &sx3, &sy3); + svg_flatten_cubic(el, sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3); + last_cx = x2; last_cy = y2; + cur_x = x3; cur_y = y3; + last_cmd = 's'; + break; + } + case 'Q': { + fixed_t x1 = pp.read_number(), y1 = pp.read_number(); + fixed_t x2 = pp.read_number(), y2 = pp.read_number(); + fixed_t sx0, sy0, sx1, sy1, sx2, sy2; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x1, y1, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + svg_flatten_quad(el, sx0, sy0, sx1, sy1, sx2, sy2); + last_cx = x1; last_cy = y1; + cur_x = x2; cur_y = y2; + last_cmd = 'Q'; + break; + } + case 'q': { + fixed_t dx1 = pp.read_number(), dy1 = pp.read_number(); + fixed_t dx2 = pp.read_number(), dy2 = pp.read_number(); + fixed_t x1 = cur_x + dx1, y1 = cur_y + dy1; + fixed_t x2 = cur_x + dx2, y2 = cur_y + dy2; + fixed_t sx0, sy0, sx1, sy1, sx2, sy2; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x1, y1, &sx1, &sy1); + scale_pt(x2, y2, &sx2, &sy2); + svg_flatten_quad(el, sx0, sy0, sx1, sy1, sx2, sy2); + last_cx = x1; last_cy = y1; + cur_x = x2; cur_y = y2; + last_cmd = 'q'; + break; + } + case 'A': case 'a': { + // Arc command: consume parameters but approximate as a line + // (arcs are rare in these icons) + fixed_t rx = pp.read_number(); + fixed_t ry = pp.read_number(); + pp.read_number(); // x-rotation + pp.read_number(); // large-arc-flag + pp.read_number(); // sweep-flag + fixed_t x = pp.read_number(); + fixed_t y = pp.read_number(); + if (cmd == 'a') { x += cur_x; y += cur_y; } + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(x, y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + cur_x = x; cur_y = y; + last_cmd = cmd; + (void)rx; (void)ry; + break; + } + case 'Z': case 'z': { + if (cur_x != start_x || cur_y != start_y) { + fixed_t sx0, sy0, sx1, sy1; + scale_pt(cur_x, cur_y, &sx0, &sy0); + scale_pt(start_x, start_y, &sx1, &sy1); + el.add(sx0, sy0, sx1, sy1); + } + cur_x = start_x; cur_y = start_y; + last_cmd = 'Z'; + break; + } + default: + // Unknown command, skip + break; + } + } +} + +// --------------------------------------------------------------------------- +// Scanline rasterizer (even-odd fill rule) +// --------------------------------------------------------------------------- +inline void svg_rasterize(const SvgEdgeList& el, uint32_t* pixels, int w, int h, uint32_t fill) { + // Temporary array for x-intersections on each scanline + // Allocate enough for all edges (each edge can intersect at most once per scanline) + int maxIsect = el.count + 16; + fixed_t* isect = (fixed_t*)montauk::malloc(maxIsect * sizeof(fixed_t)); + + for (int y = 0; y < h; ++y) { + // Scanline center in fixed-point + fixed_t scanY = int_to_fixed(y) + (1 << 15); // y + 0.5 + + int isectCount = 0; + + // Find intersections with all edges + for (int i = 0; i < el.count; ++i) { + const SvgEdge& e = el.edges[i]; + fixed_t ey0 = e.y0, ey1 = e.y1; + + // Ensure ey0 <= ey1 for the range check + fixed_t emin = ey0 < ey1 ? ey0 : ey1; + fixed_t emax = ey0 > ey1 ? ey0 : ey1; + + // Does this edge cross scanY? + if (scanY < emin || scanY >= emax) continue; + + // Compute x at intersection: x = x0 + (scanY - y0) * (x1 - x0) / (y1 - y0) + fixed_t dy = ey1 - ey0; + if (dy == 0) continue; // horizontal, skip + fixed_t dx = e.x1 - e.x0; + fixed_t t_num = scanY - ey0; + // x_intersect = x0 + dx * t_num / dy + fixed_t x_int = e.x0 + (int32_t)(((int64_t)dx * t_num) / dy); + + if (isectCount < maxIsect) + isect[isectCount++] = x_int; + } + + // Sort intersections (simple insertion sort -- usually very few) + for (int i = 1; i < isectCount; ++i) { + fixed_t key = isect[i]; + int j = i - 1; + while (j >= 0 && isect[j] > key) { + isect[j + 1] = isect[j]; + --j; + } + isect[j + 1] = key; + } + + // Fill between pairs (even-odd rule) + for (int i = 0; i + 1 < isectCount; i += 2) { + int x0 = fixed_to_int(isect[i]); + int x1 = fixed_to_int(isect[i + 1]); + + // Clamp to pixel bounds + if (x0 < 0) x0 = 0; + if (x1 > w) x1 = w; + + for (int x = x0; x < x1; ++x) { + pixels[y * w + x] = fill; + } + } + } + + montauk::mfree(isect); +} + +// --------------------------------------------------------------------------- +// Parse CSS class color mappings out of a "); + if (se) + svg_parse_css_table(sp, (int)(se - sp), &css); + } + } + + // Shared edge list (cleared per element for multi-color support) + SvgEdgeList el; + el.init(SVG_MAX_EDGES); + + // Heap-allocated path data buffer (avoids 8 KiB on the stack) + char* d_buf = (char*)montauk::malloc(SVG_MAX_PATH_LEN); + + // Group fill inheritance stack: track so child elements inherit + static constexpr int MAX_GROUP_DEPTH = 8; + struct GroupFill { Color color; bool has_fill; }; + GroupFill g_stack[MAX_GROUP_DEPTH]; + int g_depth = 0; + + // Scan for blocks (they define reusable items, not rendered directly) + const char* p = svg_data; + const char* end = svg_data + svg_len; + + while (p < end) { + // Find next '<' + while (p < end && *p != '<') ++p; + if (p >= end) break; + + int remaining = (int)(end - p); + + // Skip ... blocks entirely + if (remaining > 5 && svg_strncmp(p, "')) { + const char* defs_end = svg_strstr(p, remaining, ""); + if (defs_end) { + p = defs_end + 7; // skip past + } else { + p += 5; + } + continue; + } + + // Track closing tags to pop the group fill stack + if (remaining > 3 && svg_strncmp(p, "", 4)) { + if (g_depth > 0) g_depth--; + p += 4; + continue; + } + + // Track opening tags for fill inheritance + if (remaining > 2 && svg_strncmp(p, "')) { + const char* g_start = p; + const char* g_end = p; + while (g_end < end && *g_end != '>') ++g_end; + if (g_end < end) ++g_end; + int g_len = (int)(g_end - g_start); + + if (g_depth < MAX_GROUP_DEPTH) { + g_stack[g_depth].has_fill = false; + Color gc = fill_color; + char fbuf[64]; + int fLen = svg_get_attr(g_start, g_len, " fill", fbuf, sizeof(fbuf)); + if (fLen > 0) { + int fr = svg_resolve_fill_value(fbuf, &gc, &grads); + if (fr == 1) { + g_stack[g_depth].color = gc; + g_stack[g_depth].has_fill = true; + } else if (fr == -1) { + // fill="none" on group — children inherit none + g_stack[g_depth].has_fill = false; + } + } + g_depth++; + } + p = g_end; + continue; + } + + // Check for 5 && svg_strncmp(p, " + Color elem_color = fill_color; + // Apply inherited group fill as default + for (int gi = g_depth - 1; gi >= 0; gi--) { + if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; } + } + int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css); + if (fillResult == -1) { p = elem_end; continue; } // fill="none" + + int alpha = svg_get_element_opacity(elem_start, elem_len); + + // Extract and rasterize path + int d_len = svg_get_attr(elem_start, elem_len, " d", d_buf, SVG_MAX_PATH_LEN); + if (d_len > 0) { + el.clear(); + svg_path_to_edges(el, d_buf, d_len, scale_x, scale_y, vb_x, vb_y); + if (el.count > 0) + svg_rasterize_blend(el, icon.pixels, target_w, target_h, elem_color.to_pixel(), alpha); + } + + p = elem_end; + continue; + } + + // Check for 7 && svg_strncmp(p, "= 0; gi--) { + if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; } + } + int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css); + if (fillResult == -1) { p = elem_end; continue; } + + int alpha = svg_get_element_opacity(elem_start, elem_len); + + char attr_buf[32]; + fixed_t cx = 0, cy = 0, r = 0; + if (svg_get_attr(elem_start, elem_len, " cx", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &cx); + if (svg_get_attr(elem_start, elem_len, " cy", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &cy); + if (svg_get_attr(elem_start, elem_len, " r", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &r); + + fixed_t scx = fixed_mul(cx - vb_x, scale_x); + fixed_t scy = fixed_mul(cy - vb_y, scale_y); + fixed_t srx = fixed_mul(r, scale_x); + fixed_t sry = fixed_mul(r, scale_y); + fixed_t sr = (srx + sry) >> 1; + + el.clear(); + svg_circle_edges(el, scx, scy, sr); + if (el.count > 0) + svg_rasterize_blend(el, icon.pixels, target_w, target_h, elem_color.to_pixel(), alpha); + + p = elem_end; + continue; + } + + // Check for 5 && svg_strncmp(p, "= 0; gi--) { + if (g_stack[gi].has_fill) { elem_color = g_stack[gi].color; break; } + } + int fillResult = svg_get_element_fill(elem_start, elem_len, &elem_color, &grads, &css); + if (fillResult == -1) { p = elem_end; continue; } + + int alpha = svg_get_element_opacity(elem_start, elem_len); + + char attr_buf[32]; + fixed_t rx_val = 0, ry_val = 0, rw = 0, rh = 0, rrx = 0, rry = 0; + + if (svg_get_attr(elem_start, elem_len, " x", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &rx_val); + if (svg_get_attr(elem_start, elem_len, " y", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &ry_val); + if (svg_get_attr(elem_start, elem_len, " width", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &rw); + if (svg_get_attr(elem_start, elem_len, " height", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &rh); + if (svg_get_attr(elem_start, elem_len, " rx", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &rrx); + if (svg_get_attr(elem_start, elem_len, " ry", attr_buf, sizeof(attr_buf)) > 0) + svg_parse_fixed(attr_buf, &rry); + + fixed_t sx = fixed_mul(rx_val - vb_x, scale_x); + fixed_t sy = fixed_mul(ry_val - vb_y, scale_y); + fixed_t sw = fixed_mul(rw, scale_x); + fixed_t sh = fixed_mul(rh, scale_y); + fixed_t srx = fixed_mul(rrx, scale_x); + fixed_t sry = fixed_mul(rry, scale_y); + + el.clear(); + svg_rect_edges(el, sx, sy, sw, sh, srx, sry); + if (el.count > 0) + svg_rasterize_blend(el, icon.pixels, target_w, target_h, elem_color.to_pixel(), alpha); + + p = elem_end; + continue; + } + + ++p; + } + + montauk::mfree(d_buf); + montauk::mfree(el.edges); + return icon; +} + +// --------------------------------------------------------------------------- +// Load SVG from VFS and render +// --------------------------------------------------------------------------- +inline SvgIcon svg_load(const char* vfs_path, int target_w, int target_h, Color fill_color) { + int fd = montauk::open(vfs_path); + if (fd < 0) { + return {nullptr, 0, 0}; + } + + uint64_t size = montauk::getsize(fd); + if (size == 0 || size > SVG_MAX_FILE_SIZE) { + montauk::close(fd); + return {nullptr, 0, 0}; + } + + char* buf = (char*)montauk::malloc(size + 1); + montauk::read(fd, (uint8_t*)buf, 0, size); + montauk::close(fd); + buf[size] = '\0'; + + // 4x supersampling: render at 4x resolution, then downsample with box filter + static constexpr int SS = 4; + int hi_w = target_w * SS; + int hi_h = target_h * SS; + + SvgIcon hi = svg_render(buf, (int)size, hi_w, hi_h, fill_color); + montauk::mfree(buf); + + if (!hi.pixels) return {nullptr, 0, 0}; + + // Allocate final icon at target resolution + uint32_t* out = (uint32_t*)montauk::malloc(target_w * target_h * 4); + for (int i = 0; i < target_w * target_h; i++) out[i] = 0; + + // Downsample: average each SSxSS block using premultiplied alpha + for (int dy = 0; dy < target_h; dy++) { + for (int dx = 0; dx < target_w; dx++) { + uint32_t sum_a = 0, sum_pr = 0, sum_pg = 0, sum_pb = 0; + for (int sy = 0; sy < SS; sy++) { + for (int sx = 0; sx < SS; sx++) { + uint32_t px = hi.pixels[(dy * SS + sy) * hi_w + (dx * SS + sx)]; + uint32_t a = (px >> 24) & 0xFF; + uint32_t r = (px >> 16) & 0xFF; + uint32_t g = (px >> 8) & 0xFF; + uint32_t b = px & 0xFF; + // Premultiply before averaging (rasterizer outputs straight alpha) + sum_a += a; + sum_pr += r * a; + sum_pg += g * a; + sum_pb += b * a; + } + } + uint32_t avg_a = sum_a / (SS * SS); + + // Un-premultiply for final straight-alpha output + uint32_t avg_r = 0, avg_g = 0, avg_b = 0; + if (sum_a > 0) { + avg_r = sum_pr / sum_a; + avg_g = sum_pg / sum_a; + avg_b = sum_pb / sum_a; + if (avg_r > 255) avg_r = 255; + if (avg_g > 255) avg_g = 255; + if (avg_b > 255) avg_b = 255; + } + + out[dy * target_w + dx] = (avg_a << 24) | (avg_r << 16) | (avg_g << 8) | avg_b; + } + } + + montauk::mfree(hi.pixels); + return {out, target_w, target_h}; +} + +// --------------------------------------------------------------------------- +// Free icon pixel data +// --------------------------------------------------------------------------- +inline void svg_free(SvgIcon& icon) { + if (icon.pixels) montauk::mfree(icon.pixels); + icon.pixels = nullptr; + icon.width = 0; + icon.height = 0; +} + +} // namespace gui diff --git a/template/sysroot/include/gui/terminal.hpp b/template/sysroot/include/gui/terminal.hpp new file mode 100644 index 0000000..65c1a54 --- /dev/null +++ b/template/sysroot/include/gui/terminal.hpp @@ -0,0 +1,688 @@ +/* + * terminal.hpp + * MontaukOS terminal emulator with ANSI escape sequence support + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/font.hpp" +#include +#include +#include + +namespace gui { + +struct TermCell { + char ch; + Color fg; + Color bg; +}; + +static constexpr int TERM_MAX_SCROLLBACK = 500; + +struct TerminalState { + TermCell* cells; + TermCell* alt_cells; // alternate screen buffer + int cols, rows; + int cursor_x, cursor_y; + int saved_cursor_x, saved_cursor_y; // saved cursor for alternate screen + int scrollback_lines; // lines of history above visible screen (0..max_scrollback) + int max_scrollback; // 0 for viewers (klog), TERM_MAX_SCROLLBACK for terminal + int view_offset; // how many rows scrolled back (0 = live view) + int child_pid; + void* desktop; // DesktopState* for closing window on child exit + Color current_fg; + Color current_bg; + bool cursor_visible; + bool alt_screen_active; + bool reverse_video; + bool dirty; // true when content changed since last render + + enum { STATE_NORMAL, STATE_ESC, STATE_CSI } parse_state; + bool csi_private; // true if '?' was seen after CSI + int csi_params[8]; + int csi_param_count; + int csi_current_param; +}; + +// Standard ANSI color palette as ARGB pixels +static inline Color term_ansi_color(int idx) { + switch (idx) { + case 0: return Color::from_hex(0x000000); + case 1: return Color::from_hex(0xCC0000); + case 2: return Color::from_hex(0x4E9A06); + case 3: return Color::from_hex(0xC4A000); + case 4: return Color::from_hex(0x3465A4); + case 5: return Color::from_hex(0x75507B); + case 6: return Color::from_hex(0x06989A); + case 7: return Color::from_hex(0xD3D7CF); + case 8: return Color::from_hex(0x555753); + case 9: return Color::from_hex(0xEF2929); + case 10: return Color::from_hex(0x8AE234); + case 11: return Color::from_hex(0xFCE94F); + case 12: return Color::from_hex(0x729FCF); + case 13: return Color::from_hex(0xAD7FA8); + case 14: return Color::from_hex(0x34E2E2); + case 15: return Color::from_hex(0xEEEEEC); + default: return colors::TERM_FG; + } +} + +// Helper: pointer to start of screen-relative row r in the cells buffer +static inline TermCell* term_screen_row(TerminalState* t, int r) { + return &t->cells[(t->scrollback_lines + r) * t->cols]; +} + +static inline void terminal_scroll_up(TerminalState* t) { + if (!t->alt_screen_active && t->scrollback_lines < t->max_scrollback) { + // Room for scrollback: top visible row becomes scrollback, no data movement + t->scrollback_lines++; + } else if (!t->alt_screen_active && t->max_scrollback > 0) { + // Scrollback full: discard oldest line, shift entire buffer up by one row + int total = (t->max_scrollback + t->rows - 1) * t->cols * sizeof(TermCell); + montauk::memmove(t->cells, t->cells + t->cols, total); + } else { + // Alt screen or no scrollback (klog): shift visible area up + TermCell* screen = term_screen_row(t, 0); + montauk::memmove(screen, screen + t->cols, (t->rows - 1) * t->cols * sizeof(TermCell)); + } + + // Clear the new bottom visible row + TermCell* bottom = term_screen_row(t, t->rows - 1); + for (int c = 0; c < t->cols; c++) { + bottom[c] = {' ', t->current_fg, colors::TERM_BG}; + } + + // Keep user's scrolled-back viewport stable + if (t->view_offset > 0) { + t->view_offset++; + if (t->view_offset > t->scrollback_lines) + t->view_offset = t->scrollback_lines; + } +} + +// Initialize only the cell grid (no child process). Used by viewers like klog. +// max_sb = 0 for viewers, TERM_MAX_SCROLLBACK for the real terminal. +static inline void terminal_init_cells(TerminalState* t, int cols, int rows, int max_sb = 0) { + t->cols = cols; + t->rows = rows; + t->cursor_x = 0; + t->cursor_y = 0; + t->saved_cursor_x = 0; + t->saved_cursor_y = 0; + t->scrollback_lines = 0; + t->max_scrollback = max_sb; + t->view_offset = 0; + t->current_fg = colors::TERM_FG; + t->current_bg = colors::TERM_BG; + t->cursor_visible = false; + t->alt_screen_active = false; + t->reverse_video = false; + t->dirty = true; + t->parse_state = TerminalState::STATE_NORMAL; + t->csi_private = false; + t->csi_param_count = 0; + t->csi_current_param = 0; + t->child_pid = 0; + + int total_cells = (rows + max_sb) * cols; + int screen_cells = rows * cols; + t->cells = (TermCell*)montauk::alloc(total_cells * sizeof(TermCell)); + t->alt_cells = (TermCell*)montauk::alloc(screen_cells * sizeof(TermCell)); + if (!t->cells || !t->alt_cells) { + // Allocation failed — leave terminal in a safe but unusable state + if (t->cells) { montauk::free(t->cells); t->cells = nullptr; } + if (t->alt_cells) { montauk::free(t->alt_cells); t->alt_cells = nullptr; } + t->cols = 0; t->rows = 0; + return; + } + for (int i = 0; i < total_cells; i++) { + t->cells[i] = {' ', colors::TERM_FG, colors::TERM_BG}; + } + for (int i = 0; i < screen_cells; i++) { + t->alt_cells[i] = {' ', colors::TERM_FG, colors::TERM_BG}; + } +} + +static inline void terminal_init(TerminalState* t, int cols, int rows) { + terminal_init_cells(t, cols, rows, TERM_MAX_SCROLLBACK); + t->cursor_visible = true; + + t->child_pid = montauk::spawn_redir("0:/os/shell.elf"); + if (t->child_pid > 0) + montauk::childio_settermsz(t->child_pid, cols, rows); +} + +static inline void terminal_put_char(TerminalState* t, char ch) { + if (t->cursor_x >= t->cols) { + t->cursor_x = 0; + t->cursor_y++; + } + if (t->cursor_y >= t->rows) { + terminal_scroll_up(t); + t->cursor_y = t->rows - 1; + } + TermCell* row = term_screen_row(t, t->cursor_y); + row[t->cursor_x].ch = ch; + row[t->cursor_x].fg = t->current_fg; + row[t->cursor_x].bg = t->current_bg; + t->cursor_x++; +} + +static inline void terminal_enter_alt_screen(TerminalState* t) { + if (t->alt_screen_active) return; + t->alt_screen_active = true; + t->dirty = true; + // Save cursor + t->saved_cursor_x = t->cursor_x; + t->saved_cursor_y = t->cursor_y; + // Save visible screen to alt_cells, clear visible screen + int total = t->cols * t->rows; + TermCell* screen = term_screen_row(t, 0); + for (int i = 0; i < total; i++) { + t->alt_cells[i] = screen[i]; + screen[i] = {' ', colors::TERM_FG, colors::TERM_BG}; + } + t->view_offset = 0; + t->cursor_x = 0; + t->cursor_y = 0; +} + +static inline void terminal_exit_alt_screen(TerminalState* t) { + if (!t->alt_screen_active) return; + t->alt_screen_active = false; + t->dirty = true; + // Restore visible screen from alt_cells + int total = t->cols * t->rows; + TermCell* screen = term_screen_row(t, 0); + for (int i = 0; i < total; i++) { + screen[i] = t->alt_cells[i]; + } + // Restore cursor + t->cursor_x = t->saved_cursor_x; + t->cursor_y = t->saved_cursor_y; +} + +static inline void terminal_process_private_mode(TerminalState* t, char cmd) { + int p0 = t->csi_param_count > 0 ? t->csi_params[0] : 0; + + if (cmd == 'h') { + // Set private mode + if (p0 == 25) { + t->cursor_visible = true; + } else if (p0 == 1049) { + terminal_enter_alt_screen(t); + } + } else if (cmd == 'l') { + // Reset private mode + if (p0 == 25) { + t->cursor_visible = false; + } else if (p0 == 1049) { + terminal_exit_alt_screen(t); + } + } +} + +static inline void terminal_process_csi(TerminalState* t, char cmd) { + // Finalize current param + if (t->csi_param_count < 8) { + t->csi_params[t->csi_param_count] = t->csi_current_param; + t->csi_param_count++; + } + + // Handle private mode sequences (ESC[?...) + if (t->csi_private) { + terminal_process_private_mode(t, cmd); + return; + } + + int p0 = t->csi_param_count > 0 ? t->csi_params[0] : 0; + int p1 = t->csi_param_count > 1 ? t->csi_params[1] : 0; + + switch (cmd) { + case 'H': case 'f': { + // Cursor position: ESC[row;colH (1-based) + int row = (p0 > 0 ? p0 : 1) - 1; + int col = (p1 > 0 ? p1 : 1) - 1; + if (row < 0) row = 0; + if (row >= t->rows) row = t->rows - 1; + if (col < 0) col = 0; + if (col >= t->cols) col = t->cols - 1; + t->cursor_y = row; + t->cursor_x = col; + break; + } + case 'A': { + // Cursor up + int n = p0 > 0 ? p0 : 1; + t->cursor_y -= n; + if (t->cursor_y < 0) t->cursor_y = 0; + break; + } + case 'B': { + // Cursor down + int n = p0 > 0 ? p0 : 1; + t->cursor_y += n; + if (t->cursor_y >= t->rows) t->cursor_y = t->rows - 1; + break; + } + case 'C': { + // Cursor forward + int n = p0 > 0 ? p0 : 1; + t->cursor_x += n; + if (t->cursor_x >= t->cols) t->cursor_x = t->cols - 1; + break; + } + case 'D': { + // Cursor backward + int n = p0 > 0 ? p0 : 1; + t->cursor_x -= n; + if (t->cursor_x < 0) t->cursor_x = 0; + break; + } + case 'J': { + // Erase in display + if (p0 == 0) { + // Clear from cursor to end + TermCell* row = term_screen_row(t, t->cursor_y); + for (int x = t->cursor_x; x < t->cols; x++) + row[x] = {' ', t->current_fg, colors::TERM_BG}; + for (int r = t->cursor_y + 1; r < t->rows; r++) { + TermCell* rp = term_screen_row(t, r); + for (int c = 0; c < t->cols; c++) + rp[c] = {' ', t->current_fg, colors::TERM_BG}; + } + } else if (p0 == 1) { + // Clear from start to cursor + for (int r = 0; r < t->cursor_y; r++) { + TermCell* rp = term_screen_row(t, r); + for (int c = 0; c < t->cols; c++) + rp[c] = {' ', t->current_fg, colors::TERM_BG}; + } + TermCell* row = term_screen_row(t, t->cursor_y); + for (int x = 0; x <= t->cursor_x; x++) + row[x] = {' ', t->current_fg, colors::TERM_BG}; + } else if (p0 == 2) { + // Clear entire screen + for (int r = 0; r < t->rows; r++) { + TermCell* rp = term_screen_row(t, r); + for (int c = 0; c < t->cols; c++) + rp[c] = {' ', t->current_fg, colors::TERM_BG}; + } + t->cursor_x = 0; + t->cursor_y = 0; + } + break; + } + case 'K': { + // Erase in line + int start = 0, end = t->cols; + if (p0 == 0) { start = t->cursor_x; end = t->cols; } + else if (p0 == 1) { start = 0; end = t->cursor_x + 1; } + else if (p0 == 2) { start = 0; end = t->cols; } + TermCell* row = term_screen_row(t, t->cursor_y); + for (int x = start; x < end; x++) + row[x] = {' ', t->current_fg, colors::TERM_BG}; + break; + } + case 'm': { + // SGR - Set Graphics Rendition + for (int i = 0; i < t->csi_param_count; i++) { + int code = t->csi_params[i]; + if (code == 0) { + t->current_fg = colors::TERM_FG; + t->current_bg = colors::TERM_BG; + t->reverse_video = false; + } else if (code == 1) { + // Bold: map to bright version of current color + uint8_t r = t->current_fg.r; + uint8_t g = t->current_fg.g; + uint8_t b = t->current_fg.b; + int add = 50; + r = (r + add > 255) ? 255 : r + add; + g = (g + add > 255) ? 255 : g + add; + b = (b + add > 255) ? 255 : b + add; + t->current_fg = Color::from_rgb(r, g, b); + } else if (code == 2) { + // Dim: darken current fg color + t->current_fg.r = t->current_fg.r / 2; + t->current_fg.g = t->current_fg.g / 2; + t->current_fg.b = t->current_fg.b / 2; + } else if (code == 7) { + // Reverse video + if (!t->reverse_video) { + t->reverse_video = true; + Color tmp = t->current_fg; + t->current_fg = t->current_bg; + t->current_bg = tmp; + } + } else if (code == 27) { + // Reverse off + if (t->reverse_video) { + t->reverse_video = false; + Color tmp = t->current_fg; + t->current_fg = t->current_bg; + t->current_bg = tmp; + } + } else if (code >= 30 && code <= 37) { + t->current_fg = term_ansi_color(code - 30); + if (t->reverse_video) { + // In reverse mode, fg is displayed as bg + Color tmp = t->current_fg; + t->current_fg = t->current_bg; + t->current_bg = tmp; + } + } else if (code >= 40 && code <= 47) { + t->current_bg = term_ansi_color(code - 40); + } else if (code >= 90 && code <= 97) { + t->current_fg = term_ansi_color(code - 90 + 8); + } else if (code >= 100 && code <= 107) { + t->current_bg = term_ansi_color(code - 100 + 8); + } else if (code == 39) { + t->current_fg = colors::TERM_FG; + } else if (code == 49) { + t->current_bg = colors::TERM_BG; + } + } + if (t->csi_param_count == 0) { + // ESC[m with no params = reset + t->current_fg = colors::TERM_FG; + t->current_bg = colors::TERM_BG; + t->reverse_video = false; + } + break; + } + default: + break; + } +} + +static inline void terminal_feed(TerminalState* t, const char* data, int len) { + if (len > 0) t->dirty = true; + for (int i = 0; i < len; i++) { + char ch = data[i]; + + switch (t->parse_state) { + case TerminalState::STATE_NORMAL: + if (ch == '\033') { + t->parse_state = TerminalState::STATE_ESC; + } else if (ch == '\n') { + t->cursor_x = 0; // CR+LF: shell sends \n without \r + t->cursor_y++; + if (t->cursor_y >= t->rows) { + terminal_scroll_up(t); + t->cursor_y = t->rows - 1; + } + } else if (ch == '\r') { + t->cursor_x = 0; + } else if (ch == '\b') { + if (t->cursor_x > 0) t->cursor_x--; + } else if (ch == '\t') { + int next = (t->cursor_x + 8) & ~7; + if (next > t->cols) next = t->cols; + while (t->cursor_x < next) { + terminal_put_char(t, ' '); + } + } else if (ch >= 32 || ch < 0) { + // Printable character (also treat high-bit chars as printable) + terminal_put_char(t, ch); + } + break; + + case TerminalState::STATE_ESC: + if (ch == '[') { + t->parse_state = TerminalState::STATE_CSI; + t->csi_private = false; + t->csi_param_count = 0; + t->csi_current_param = 0; + for (int j = 0; j < 8; j++) t->csi_params[j] = 0; + } else if (ch == 'c') { + // Reset terminal + t->current_fg = colors::TERM_FG; + t->current_bg = colors::TERM_BG; + t->cursor_x = 0; + t->cursor_y = 0; + t->parse_state = TerminalState::STATE_NORMAL; + } else { + // Unknown ESC sequence, ignore + t->parse_state = TerminalState::STATE_NORMAL; + } + break; + + case TerminalState::STATE_CSI: + if (ch >= '0' && ch <= '9') { + t->csi_current_param = t->csi_current_param * 10 + (ch - '0'); + } else if (ch == ';') { + if (t->csi_param_count < 8) { + t->csi_params[t->csi_param_count] = t->csi_current_param; + t->csi_param_count++; + } + t->csi_current_param = 0; + } else if (ch == '?') { + t->csi_private = true; + } else if (ch >= 0x40 && ch <= 0x7E) { + // Final byte - execute command + terminal_process_csi(t, ch); + t->parse_state = TerminalState::STATE_NORMAL; + } else { + // Unknown, abort CSI + t->parse_state = TerminalState::STATE_NORMAL; + } + break; + } + } +} + +static inline void terminal_render(TerminalState* t, uint32_t* pixels, int pw, int ph) { + if (!t->dirty || !t->cells) return; + t->dirty = false; + + int cell_w = mono_cell_width(); + int cell_h = mono_cell_height(); + bool use_ttf = fonts::mono && fonts::mono->valid; + GlyphCache* gc = use_ttf ? fonts::mono->get_cache(fonts::TERM_SIZE) : nullptr; + + // Fill background using row-copy: fill first row, then memcpy to the rest + uint32_t bg_px = colors::TERM_BG.to_pixel(); + int row_bytes = pw * sizeof(uint32_t); + for (int i = 0; i < pw; i++) pixels[i] = bg_px; + for (int r = 1; r < ph; r++) { + montauk::memcpy(&pixels[r * pw], pixels, row_bytes); + } + + // Determine which rows of the buffer to display + int base_row = t->scrollback_lines - t->view_offset; + if (base_row < 0) base_row = 0; + + // Render each visible cell + int visible_rows = ph / cell_h; + int visible_cols = pw / cell_w; + if (visible_rows > t->rows) visible_rows = t->rows; + if (visible_cols > t->cols) visible_cols = t->cols; + + for (int r = 0; r < visible_rows; r++) { + int py = r * cell_h; + int src_row = base_row + r; + for (int c = 0; c < visible_cols; c++) { + int idx = src_row * t->cols + c; + TermCell& cell = t->cells[idx]; + + int px = c * cell_w; + + // Only draw cell background if it differs from terminal bg + uint32_t cell_bg = cell.bg.to_pixel(); + if (cell_bg != bg_px) { + for (int fy = 0; fy < cell_h && py + fy < ph; fy++) { + uint32_t* row = &pixels[(py + fy) * pw + px]; + for (int fx = 0; fx < cell_w && px + fx < pw; fx++) { + row[fx] = cell_bg; + } + } + } + + // Draw character glyph + if (cell.ch > 32 || cell.ch < 0) { + if (use_ttf) { + int baseline = py + gc->ascent; + fonts::mono->draw_char_to_buffer(pixels, pw, ph, + px, baseline, (unsigned char)cell.ch, cell.fg, gc); + } else { + uint32_t cell_fg = cell.fg.to_pixel(); + const uint8_t* glyph = &font_data[(unsigned char)cell.ch * FONT_HEIGHT]; + for (int fy = 0; fy < FONT_HEIGHT; fy++) { + int dy = py + fy; + if (dy >= ph) break; + uint8_t bits = glyph[fy]; + for (int fx = 0; fx < FONT_WIDTH; fx++) { + if (bits & (0x80 >> fx)) { + int dx = px + fx; + if (dx >= pw) break; + pixels[dy * pw + dx] = cell_fg; + } + } + } + } + } + } + } + + // Draw cursor (only when viewing live position) + if (t->view_offset == 0 && t->cursor_visible && + t->cursor_x < visible_cols && t->cursor_y < visible_rows) { + int cx = t->cursor_x * cell_w; + int cy = t->cursor_y * cell_h; + uint32_t cursor_px = colors::WHITE.to_pixel(); + for (int fy = 0; fy < cell_h; fy++) { + int dy = cy + fy; + if (dy >= ph) break; + for (int fx = 0; fx < cell_w; fx++) { + int dx = cx + fx; + if (dx >= pw) break; + pixels[dy * pw + dx] = cursor_px; + } + } + // Draw character on top of cursor in black + if (t->cursor_y < t->rows && t->cursor_x < t->cols) { + TermCell* row = term_screen_row(t, t->cursor_y); + char ch = row[t->cursor_x].ch; + if (ch > 32 || ch < 0) { + if (use_ttf) { + int baseline = cy + gc->ascent; + fonts::mono->draw_char_to_buffer(pixels, pw, ph, + cx, baseline, (unsigned char)ch, colors::BLACK, gc); + } else { + const uint8_t* glyph = &font_data[(unsigned char)ch * FONT_HEIGHT]; + uint32_t black_px = colors::BLACK.to_pixel(); + for (int fy = 0; fy < FONT_HEIGHT; fy++) { + int dy = cy + fy; + if (dy >= ph) break; + uint8_t bits = glyph[fy]; + for (int fx = 0; fx < FONT_WIDTH; fx++) { + if (bits & (0x80 >> fx)) { + int dx = cx + fx; + if (dx >= pw) break; + pixels[dy * pw + dx] = black_px; + } + } + } + } + } + } + } +} + +static inline void terminal_resize(TerminalState* t, int new_cols, int new_rows) { + if (new_cols == t->cols && new_rows == t->rows) return; + if (new_cols < 1 || new_rows < 1) return; + t->dirty = true; + + int new_capacity = new_rows + t->max_scrollback; + int new_total = new_capacity * new_cols; + TermCell* new_cells = (TermCell*)montauk::alloc(new_total * sizeof(TermCell)); + TermCell* new_alt = (TermCell*)montauk::alloc(new_rows * new_cols * sizeof(TermCell)); + if (!new_cells || !new_alt) { + if (new_cells) montauk::free(new_cells); + if (new_alt) montauk::free(new_alt); + return; // keep existing buffers + } + + // Clear new buffers + for (int i = 0; i < new_total; i++) + new_cells[i] = {' ', colors::TERM_FG, colors::TERM_BG}; + for (int i = 0; i < new_rows * new_cols; i++) + new_alt[i] = {' ', colors::TERM_FG, colors::TERM_BG}; + + // Copy content: scrollback + visible screen + int old_content = t->scrollback_lines + t->rows; + int keep = old_content < new_capacity ? old_content : new_capacity; + int discard = old_content - keep; + int copy_cols = t->cols < new_cols ? t->cols : new_cols; + + for (int r = 0; r < keep; r++) { + for (int c = 0; c < copy_cols; c++) { + new_cells[r * new_cols + c] = t->cells[(discard + r) * t->cols + c]; + } + } + + int new_scrollback = keep - new_rows; + if (new_scrollback < 0) new_scrollback = 0; + + // Adjust cursor + int abs_cursor_y = t->scrollback_lines + t->cursor_y - discard; + int new_cursor_y = abs_cursor_y - new_scrollback; + if (new_cursor_y < 0) new_cursor_y = 0; + if (new_cursor_y >= new_rows) new_cursor_y = new_rows - 1; + int new_cursor_x = t->cursor_x < new_cols ? t->cursor_x : new_cols - 1; + + if (t->cells) montauk::free(t->cells); + if (t->alt_cells) montauk::free(t->alt_cells); + + t->cells = new_cells; + t->alt_cells = new_alt; + t->cols = new_cols; + t->rows = new_rows; + t->scrollback_lines = new_scrollback; + t->cursor_x = new_cursor_x; + t->cursor_y = new_cursor_y; + + // Clamp view offset + if (t->view_offset > t->scrollback_lines) + t->view_offset = t->scrollback_lines; + + // Notify child process of new terminal size + if (t->child_pid > 0) { + montauk::childio_settermsz(t->child_pid, new_cols, new_rows); + } +} + +static inline void terminal_handle_key(TerminalState* t, const Montauk::KeyEvent& key) { + // Snap to live on any keyboard input + if (t->view_offset > 0) { + t->view_offset = 0; + t->dirty = true; + } + if (t->child_pid > 0) { + montauk::childio_writekey(t->child_pid, &key); + } +} + +// Returns false if the child process has exited +static inline bool terminal_poll(TerminalState* t) { + if (t->child_pid <= 0) return false; + char buf[4096]; + // Drain all available data so large output renders in one frame + for (;;) { + int n = montauk::childio_read(t->child_pid, buf, sizeof(buf)); + if (n > 0) { + terminal_feed(t, buf, n); + } else { + // n == -1 means child process is gone; n == 0 means no data yet + if (n < 0) { t->child_pid = 0; return false; } + break; + } + } + return true; +} + +} // namespace gui diff --git a/template/sysroot/include/gui/truetype.hpp b/template/sysroot/include/gui/truetype.hpp new file mode 100644 index 0000000..7706763 --- /dev/null +++ b/template/sysroot/include/gui/truetype.hpp @@ -0,0 +1,409 @@ +/* + * truetype.hpp + * MontaukOS TrueType font rendering via stb_truetype + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include +#include +#include +#include +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" + +// Forward-declare stbtt_fontinfo to avoid including stb_truetype.h in every TU. +// The actual struct is defined in stb_truetype.h and only used in truetype.hpp +// method bodies (which are inline but only instantiated where stb_truetype.h +// is also included — i.e. stb_truetype_impl.cpp). We include the full header +// here since our inline methods need the complete type. +#include "gui/stb_math.h" + +// We need the stb macros defined before including stb_truetype.h (header-only mode) +#ifndef STBTT_ifloor +#define STBTT_ifloor(x) ((int) stb_floor(x)) +#define STBTT_iceil(x) ((int) stb_ceil(x)) +#define STBTT_sqrt(x) stb_sqrt(x) +#define STBTT_pow(x,y) stb_pow(x,y) +#define STBTT_fmod(x,y) stb_fmod(x,y) +#define STBTT_cos(x) stb_cos(x) +#define STBTT_acos(x) stb_acos(x) +#define STBTT_fabs(x) stb_fabs(x) +#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x)) +#define STBTT_free(x,u) ((void)(u), montauk::mfree(x)) +#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n) +#define STBTT_memset(d,v,n) montauk::memset(d,v,n) +#define STBTT_strlen(x) montauk::slen(x) +#define STBTT_assert(x) ((void)(x)) +#endif + +#include "gui/stb_truetype.h" + +namespace gui { + +struct CachedGlyph { + uint8_t* bitmap; + int width, height; + int xoff, yoff; + int advance; + bool loaded; +}; + +struct GlyphCache { + CachedGlyph glyphs[256]; // Latin-1 Supplement (U+0080..U+00FF) included + int pixel_size; + float scale; + int ascent, descent, line_gap; + int line_height; +}; + +struct TrueTypeFont { + stbtt_fontinfo info; + uint8_t* data; + GlyphCache caches[4]; + int cache_count; + bool valid; + bool em_scaling; // true for PDF embedded fonts: scale by em square, not ascent-descent + + bool init(const char* vfs_path) { + valid = false; + em_scaling = false; + data = nullptr; + cache_count = 0; + + int fd = montauk::open(vfs_path); + if (fd < 0) return false; + + uint64_t size = montauk::getsize(fd); + if (size == 0 || size > 1024 * 1024) { + montauk::close(fd); + return false; + } + + data = (uint8_t*)montauk::alloc(size); + if (!data) { + montauk::close(fd); + return false; + } + + montauk::read(fd, data, 0, size); + montauk::close(fd); + + if (!stbtt_InitFont(&info, data, stbtt_GetFontOffsetForIndex(data, 0))) { + montauk::free(data); + data = nullptr; + return false; + } + + valid = true; + return true; + } + + void init_cache(GlyphCache* gc, int pixel_size) { + // Free any existing glyph bitmaps + for (int i = 0; i < 256; i++) { + if (gc->glyphs[i].bitmap) { + montauk::mfree(gc->glyphs[i].bitmap); + } + gc->glyphs[i].bitmap = nullptr; + gc->glyphs[i].loaded = false; + } + + gc->pixel_size = pixel_size; + gc->scale = em_scaling + ? stbtt_ScaleForMappingEmToPixels(&info, (float)pixel_size) + : stbtt_ScaleForPixelHeight(&info, (float)pixel_size); + + int asc, desc, lg; + stbtt_GetFontVMetrics(&info, &asc, &desc, &lg); + gc->ascent = (int)(asc * gc->scale); + gc->descent = (int)(desc * gc->scale); + gc->line_gap = (int)(lg * gc->scale); + gc->line_height = gc->ascent - gc->descent + gc->line_gap; + } + + GlyphCache* get_cache(int pixel_size) { + // Search existing caches + for (int i = 0; i < cache_count; i++) { + if (caches[i].pixel_size == pixel_size) + return &caches[i]; + } + + // Use a free slot if available + if (cache_count < 4) { + GlyphCache* gc = &caches[cache_count++]; + init_cache(gc, pixel_size); + return gc; + } + + // Evict oldest cache (slot 0) — free its glyph bitmaps + for (int g = 0; g < 256; g++) { + if (caches[0].glyphs[g].bitmap) + montauk::mfree(caches[0].glyphs[g].bitmap); + } + // Shift remaining caches down + for (int i = 0; i < 3; i++) + montauk::memcpy(&caches[i], &caches[i + 1], sizeof(GlyphCache)); + montauk::memset(&caches[3], 0, sizeof(GlyphCache)); + init_cache(&caches[3], pixel_size); + return &caches[3]; + } + + CachedGlyph* get_glyph(GlyphCache* gc, int codepoint) { + if (codepoint < 0 || codepoint >= 256) return nullptr; + CachedGlyph* g = &gc->glyphs[codepoint]; + if (g->loaded) return g; + + g->loaded = true; + int advance, lsb; + stbtt_GetCodepointHMetrics(&info, codepoint, &advance, &lsb); + g->advance = (int)(advance * gc->scale); + + int x0, y0, x1, y1; + stbtt_GetCodepointBitmapBox(&info, codepoint, gc->scale, gc->scale, + &x0, &y0, &x1, &y1); + g->width = x1 - x0; + g->height = y1 - y0; + g->xoff = x0; + g->yoff = y0; + + if (g->width > 0 && g->height > 0) { + g->bitmap = (uint8_t*)montauk::malloc(g->width * g->height); + stbtt_MakeCodepointBitmap(&info, g->bitmap, g->width, g->height, + g->width, gc->scale, gc->scale, codepoint); + } + + return g; + } + + int measure_text(const char* text, int pixel_size) { + if (!valid) return 0; + GlyphCache* gc = get_cache(pixel_size); + int w = 0; + for (int i = 0; text[i]; i++) { + CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]); + if (g) w += g->advance; + } + return w; + } + + int get_line_height(int pixel_size) { + if (!valid) return 16; + GlyphCache* gc = get_cache(pixel_size); + return gc->line_height; + } + + void draw(Framebuffer& fb, int x, int y, const char* text, + Color color, int pixel_size) { + if (!valid) return; + GlyphCache* gc = get_cache(pixel_size); + int cx = x; + int baseline = y + gc->ascent; + + for (int i = 0; text[i]; i++) { + CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]); + if (!g) continue; + + if (g->bitmap) { + int gx = cx + g->xoff; + int gy = baseline + g->yoff; + for (int row = 0; row < g->height; row++) { + for (int col = 0; col < g->width; col++) { + uint8_t alpha = g->bitmap[row * g->width + col]; + if (alpha > 0) { + Color c = {color.r, color.g, color.b, alpha}; + fb.put_pixel_alpha(gx + col, gy + row, c); + } + } + } + } + cx += g->advance; + } + } + + void draw_bg(Framebuffer& fb, int x, int y, const char* text, + Color fg, Color bg, int pixel_size) { + if (!valid) return; + GlyphCache* gc = get_cache(pixel_size); + + // Fill background for the text extent + int tw = measure_text(text, pixel_size); + fb.fill_rect(x, y, tw, gc->line_height, bg); + + // Then draw foreground + draw(fb, x, y, text, fg, pixel_size); + } + + void draw_to_buffer(uint32_t* pixels, int buf_w, int buf_h, + int x, int y, const char* text, + Color color, int pixel_size) { + if (!valid) return; + GlyphCache* gc = get_cache(pixel_size); + int cx = x; + int baseline = y + gc->ascent; + + for (int i = 0; text[i]; i++) { + CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]); + if (!g) continue; + + if (g->bitmap) { + int gx = cx + g->xoff; + int gy = baseline + g->yoff; + for (int row = 0; row < g->height; row++) { + int dy = gy + row; + if (dy < 0 || dy >= buf_h) continue; + for (int col = 0; col < g->width; col++) { + int dx = gx + col; + if (dx < 0 || dx >= buf_w) continue; + uint8_t alpha = g->bitmap[row * g->width + col]; + if (alpha == 0) continue; + + if (alpha == 255) { + pixels[dy * buf_w + dx] = + 0xFF000000 | ((uint32_t)color.r << 16) | + ((uint32_t)color.g << 8) | color.b; + } else { + uint32_t dst = pixels[dy * buf_w + dx]; + uint8_t dr = (dst >> 16) & 0xFF; + uint8_t dg = (dst >> 8) & 0xFF; + uint8_t db = dst & 0xFF; + uint32_t a = alpha, inv_a = 255 - alpha; + uint32_t rr = (a * color.r + inv_a * dr + 128) / 255; + uint32_t gg = (a * color.g + inv_a * dg + 128) / 255; + uint32_t bb = (a * color.b + inv_a * db + 128) / 255; + pixels[dy * buf_w + dx] = + 0xFF000000 | (rr << 16) | (gg << 8) | bb; + } + } + } + } + cx += g->advance; + } + } + + // Draw text to buffer with clip rectangle (pixels outside clip_x..clip_x+clip_w are not drawn) + void draw_to_buffer_clipped(uint32_t* pixels, int buf_w, int buf_h, + int x, int y, const char* text, + Color color, int pixel_size, + int clip_x, int clip_y, int clip_w, int clip_h) { + if (!valid) return; + GlyphCache* gc = get_cache(pixel_size); + int cx = x; + int baseline = y + gc->ascent; + int clip_x2 = clip_x + clip_w; + int clip_y2 = clip_y + clip_h; + + for (int i = 0; text[i]; i++) { + CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]); + if (!g) continue; + + if (g->bitmap) { + int gx = cx + g->xoff; + int gy = baseline + g->yoff; + for (int row = 0; row < g->height; row++) { + int dy = gy + row; + if (dy < clip_y || dy >= clip_y2 || dy < 0 || dy >= buf_h) continue; + for (int col = 0; col < g->width; col++) { + int dx = gx + col; + if (dx < clip_x || dx >= clip_x2 || dx < 0 || dx >= buf_w) continue; + uint8_t alpha = g->bitmap[row * g->width + col]; + if (alpha == 0) continue; + + if (alpha == 255) { + pixels[dy * buf_w + dx] = + 0xFF000000 | ((uint32_t)color.r << 16) | + ((uint32_t)color.g << 8) | color.b; + } else { + uint32_t dst = pixels[dy * buf_w + dx]; + uint8_t dr = (dst >> 16) & 0xFF; + uint8_t dg = (dst >> 8) & 0xFF; + uint8_t db = dst & 0xFF; + uint32_t a = alpha, inv_a = 255 - alpha; + uint32_t rr = (a * color.r + inv_a * dr + 128) / 255; + uint32_t gg = (a * color.g + inv_a * dg + 128) / 255; + uint32_t bb = (a * color.b + inv_a * db + 128) / 255; + pixels[dy * buf_w + dx] = + 0xFF000000 | (rr << 16) | (gg << 8) | bb; + } + } + } + } + cx += g->advance; + } + } + + // Draw single character to buffer, returning advance width + int draw_char_to_buffer(uint32_t* pixels, int buf_w, int buf_h, + int x, int baseline, int codepoint, + Color color, GlyphCache* gc) { + CachedGlyph* g = get_glyph(gc, codepoint); + if (!g) return 0; + + if (g->bitmap) { + int gx = x + g->xoff; + int gy = baseline + g->yoff; + for (int row = 0; row < g->height; row++) { + int dy = gy + row; + if (dy < 0 || dy >= buf_h) continue; + for (int col = 0; col < g->width; col++) { + int dx = gx + col; + if (dx < 0 || dx >= buf_w) continue; + uint8_t alpha = g->bitmap[row * g->width + col]; + if (alpha == 0) continue; + + if (alpha == 255) { + pixels[dy * buf_w + dx] = + 0xFF000000 | ((uint32_t)color.r << 16) | + ((uint32_t)color.g << 8) | color.b; + } else { + uint32_t dst = pixels[dy * buf_w + dx]; + uint8_t dr = (dst >> 16) & 0xFF; + uint8_t dg = (dst >> 8) & 0xFF; + uint8_t db = dst & 0xFF; + uint32_t a = alpha, inv_a = 255 - alpha; + uint32_t rr = (a * color.r + inv_a * dr + 128) / 255; + uint32_t gg = (a * color.g + inv_a * dg + 128) / 255; + uint32_t bb = (a * color.b + inv_a * db + 128) / 255; + pixels[dy * buf_w + dx] = + 0xFF000000 | (rr << 16) | (gg << 8) | bb; + } + } + } + } + return g->advance; + } +}; + +// Global font manager +namespace fonts { + inline TrueTypeFont* system_font = nullptr; + inline TrueTypeFont* system_bold = nullptr; + inline TrueTypeFont* mono = nullptr; + inline TrueTypeFont* mono_bold = nullptr; + + inline int UI_SIZE = 18; + inline int TITLE_SIZE = 18; + inline int TERM_SIZE = 18; + inline int LARGE_SIZE = 28; + + inline bool init() { + auto load = [](const char* path) -> TrueTypeFont* { + TrueTypeFont* f = (TrueTypeFont*)montauk::malloc(sizeof(TrueTypeFont)); + montauk::memset(f, 0, sizeof(TrueTypeFont)); + if (!f->init(path)) { + montauk::mfree(f); + return nullptr; + } + return f; + }; + + system_font = load("0:/fonts/Roboto-Medium.ttf"); + system_bold = load("0:/fonts/Roboto-Bold.ttf"); + mono = load("0:/fonts/JetBrainsMono-Regular.ttf"); + mono_bold = load("0:/fonts/JetBrainsMono-Bold.ttf"); + + return system_font != nullptr; + } +} + +} // namespace gui diff --git a/template/sysroot/include/gui/widgets.hpp b/template/sysroot/include/gui/widgets.hpp new file mode 100644 index 0000000..56315c1 --- /dev/null +++ b/template/sysroot/include/gui/widgets.hpp @@ -0,0 +1,359 @@ +/* + * widgets.hpp + * MontaukOS GUI widget toolkit (Label, Button, TextBox, Scrollbar) + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" +#include "gui/font.hpp" +#include "gui/draw.hpp" + +namespace gui { + +// ---- Mouse event ---- + +struct MouseEvent { + int x, y; + uint8_t buttons; + uint8_t prev_buttons; + int32_t scroll; + + bool left_held() const { return buttons & 0x01; } + bool right_held() const { return buttons & 0x02; } + bool middle_held() const { return buttons & 0x04; } + + bool left_pressed() const { return (buttons & 0x01) && !(prev_buttons & 0x01); } + bool left_released() const { return !(buttons & 0x01) && (prev_buttons & 0x01); } + bool right_pressed() const { return (buttons & 0x02) && !(prev_buttons & 0x02); } + bool right_released() const { return !(buttons & 0x02) && (prev_buttons & 0x02); } +}; + +// ---- Callback types ---- + +using ClickCallback = void (*)(void* userdata); + +// ---- Label ---- + +struct Label { + int x, y; + const char* text; + Color color; + + void draw(Framebuffer& fb) const { + if (text) { + draw_text(fb, x, y, text, color); + } + } +}; + +// ---- Button ---- + +struct Button { + Rect bounds; + const char* text; + Color bg; + Color fg; + Color hover_bg; + bool hovered; + bool pressed; + ClickCallback on_click; + void* userdata; + + void init(int x, int y, int w, int h, const char* label) { + bounds = {x, y, w, h}; + text = label; + bg = colors::ACCENT; + fg = colors::WHITE; + hover_bg = Color::from_rgb(0x2B, 0x6B, 0xE0); + hovered = false; + pressed = false; + on_click = nullptr; + userdata = nullptr; + } + + void draw(Framebuffer& fb) const { + Color bg_color = hovered ? hover_bg : bg; + fill_rounded_rect(fb, bounds.x, bounds.y, bounds.w, bounds.h, 4, bg_color); + // Center text + int tw = text_width(text); + int tx = bounds.x + (bounds.w - tw) / 2; + int ty = bounds.y + (bounds.h - system_font_height()) / 2; + draw_text(fb, tx, ty, text, fg); + } + + bool handle_mouse(const MouseEvent& ev) { + hovered = bounds.contains(ev.x, ev.y); + if (hovered && ev.left_pressed()) { + pressed = true; + } + if (pressed && ev.left_released()) { + pressed = false; + if (hovered && on_click) { + on_click(userdata); + return true; + } + } + if (!ev.left_held()) { + pressed = false; + } + return false; + } +}; + +// ---- IconButton (for panel/menu items with SVG icon + optional text) ---- + +struct IconButton { + Rect bounds; + const char* text; // optional label (can be nullptr) + uint32_t* icon_pixels; // icon pixel data (ARGB) + int icon_w, icon_h; + Color bg; + Color hover_bg; + Color text_color; + bool hovered; + bool pressed; + ClickCallback on_click; + void* userdata; + + void init(int x, int y, int w, int h) { + bounds = {x, y, w, h}; + text = nullptr; + icon_pixels = nullptr; + icon_w = 0; + icon_h = 0; + bg = {0, 0, 0, 0}; // transparent by default + hover_bg = colors::MENU_HOVER; + text_color = colors::TEXT_COLOR; + hovered = false; + pressed = false; + on_click = nullptr; + userdata = nullptr; + } + + void draw(Framebuffer& fb) const { + if (hovered) { + fill_rounded_rect(fb, bounds.x, bounds.y, bounds.w, bounds.h, 3, hover_bg); + } else if (bg.a > 0) { + fill_rounded_rect(fb, bounds.x, bounds.y, bounds.w, bounds.h, 3, bg); + } + + int content_x = bounds.x + 6; + + // Draw icon + if (icon_pixels && icon_w > 0 && icon_h > 0) { + int iy = bounds.y + (bounds.h - icon_h) / 2; + fb.blit_alpha(content_x, iy, icon_w, icon_h, icon_pixels); + content_x += icon_w + 6; + } + + // Draw text + if (text) { + int ty = bounds.y + (bounds.h - system_font_height()) / 2; + draw_text(fb, content_x, ty, text, text_color); + } + } + + bool handle_mouse(const MouseEvent& ev) { + hovered = bounds.contains(ev.x, ev.y); + if (hovered && ev.left_pressed()) { + pressed = true; + } + if (pressed && ev.left_released()) { + pressed = false; + if (hovered && on_click) { + on_click(userdata); + return true; + } + } + if (!ev.left_held()) { + pressed = false; + } + return false; + } +}; + +// ---- TextBox ---- + +struct TextBox { + Rect bounds; + char text[256]; + int cursor; + int text_len; + bool focused; + Color bg; + Color fg; + Color border_color; + Color cursor_color; + + void init(int x, int y, int w, int h) { + bounds = {x, y, w, h}; + text[0] = '\0'; + cursor = 0; + text_len = 0; + focused = false; + bg = colors::WHITE; + fg = colors::TEXT_COLOR; + border_color = colors::BORDER; + cursor_color = colors::ACCENT; + } + + void draw(Framebuffer& fb) const { + fb.fill_rect(bounds.x, bounds.y, bounds.w, bounds.h, bg); + draw_rect(fb, bounds.x, bounds.y, bounds.w, bounds.h, + focused ? cursor_color : border_color); + + // Draw text with 4px padding + int tx = bounds.x + 4; + int fh = system_font_height(); + int ty = bounds.y + (bounds.h - fh) / 2; + draw_text(fb, tx, ty, text, fg); + + // Draw cursor if focused + if (focused) { + // Measure text up to cursor position for proportional fonts + char prefix[256]; + for (int i = 0; i < cursor && i < 255; i++) prefix[i] = text[i]; + prefix[cursor < 255 ? cursor : 255] = '\0'; + int cx = tx + text_width(prefix); + draw_vline(fb, cx, ty, fh, cursor_color); + } + } + + void handle_mouse(const MouseEvent& ev) { + if (ev.left_pressed()) { + focused = bounds.contains(ev.x, ev.y); + } + } + + void handle_key(const Montauk::KeyEvent& key) { + if (!focused || !key.pressed) return; + + if (key.ascii == '\b' || key.scancode == 0x0E) { + // Backspace + if (cursor > 0) { + for (int i = cursor - 1; i < text_len - 1; i++) { + text[i] = text[i + 1]; + } + text_len--; + cursor--; + text[text_len] = '\0'; + } + } else if (key.ascii >= 32 && key.ascii < 127) { + // Printable character + if (text_len < 254) { + for (int i = text_len; i > cursor; i--) { + text[i] = text[i - 1]; + } + text[cursor] = key.ascii; + cursor++; + text_len++; + text[text_len] = '\0'; + } + } else if (key.scancode == 0x4B) { + // Left arrow + if (cursor > 0) cursor--; + } else if (key.scancode == 0x4D) { + // Right arrow + if (cursor < text_len) cursor++; + } + } +}; + +// ---- Scrollbar ---- + +struct Scrollbar { + Rect bounds; + int content_height; + int view_height; + int scroll_offset; + bool dragging; + int drag_start_y; + int drag_start_offset; + Color bg; + Color fg; + Color hover_fg; + bool hovered; + + void init(int x, int y, int w, int h) { + bounds = {x, y, w, h}; + content_height = 0; + view_height = h; + scroll_offset = 0; + dragging = false; + drag_start_y = 0; + drag_start_offset = 0; + bg = colors::SCROLLBAR_BG; + fg = colors::SCROLLBAR_FG; + hover_fg = Color::from_rgb(0xA0, 0xA0, 0xA0); + hovered = false; + } + + int thumb_height() const { + if (content_height <= view_height) return bounds.h; + int th = (view_height * bounds.h) / content_height; + return th < 20 ? 20 : th; + } + + int thumb_y() const { + if (content_height <= view_height) return bounds.y; + int range = bounds.h - thumb_height(); + int max_scroll = content_height - view_height; + if (max_scroll <= 0) return bounds.y; + return bounds.y + (scroll_offset * range) / max_scroll; + } + + int max_scroll() const { + int ms = content_height - view_height; + return ms > 0 ? ms : 0; + } + + void draw(Framebuffer& fb) const { + if (content_height <= view_height) return; // no scrollbar needed + + fb.fill_rect(bounds.x, bounds.y, bounds.w, bounds.h, bg); + int th = thumb_height(); + int ty = thumb_y(); + Color thumb_color = (hovered || dragging) ? hover_fg : fg; + fill_rounded_rect(fb, bounds.x + 1, ty, bounds.w - 2, th, 3, thumb_color); + } + + void handle_mouse(const MouseEvent& ev) { + if (content_height <= view_height) return; + + Rect thumb_rect = {bounds.x, thumb_y(), bounds.w, thumb_height()}; + hovered = thumb_rect.contains(ev.x, ev.y); + + if (hovered && ev.left_pressed()) { + dragging = true; + drag_start_y = ev.y; + drag_start_offset = scroll_offset; + } + + if (dragging && ev.left_held()) { + int dy = ev.y - drag_start_y; + int range = bounds.h - thumb_height(); + if (range > 0) { + int ms = max_scroll(); + scroll_offset = drag_start_offset + (dy * ms) / range; + if (scroll_offset < 0) scroll_offset = 0; + if (scroll_offset > ms) scroll_offset = ms; + } + } + + if (!ev.left_held()) { + dragging = false; + } + + // Handle scroll wheel + if (bounds.contains(ev.x, ev.y) && ev.scroll != 0) { + scroll_offset += ev.scroll * 20; + int ms = max_scroll(); + if (scroll_offset < 0) scroll_offset = 0; + if (scroll_offset > ms) scroll_offset = ms; + } + } +}; + +} // namespace gui diff --git a/template/sysroot/include/gui/window.hpp b/template/sysroot/include/gui/window.hpp new file mode 100644 index 0000000..7c67c1d --- /dev/null +++ b/template/sysroot/include/gui/window.hpp @@ -0,0 +1,96 @@ +/* + * window.hpp + * MontaukOS window management types + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include "gui/gui.hpp" +#include "gui/framebuffer.hpp" +#include "gui/widgets.hpp" +#include + +namespace gui { + +enum WindowState { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_CLOSED }; + +enum ResizeEdge { + RESIZE_NONE = 0, + RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM, + RESIZE_TOP_LEFT, RESIZE_TOP_RIGHT, RESIZE_BOTTOM_LEFT, RESIZE_BOTTOM_RIGHT +}; + +static constexpr int TITLEBAR_HEIGHT = 30; +static constexpr int BORDER_WIDTH = 1; +static constexpr int SHADOW_SIZE = 3; +static constexpr int BTN_RADIUS = 6; +static constexpr int MAX_TITLE_LEN = 64; +static constexpr int RESIZE_GRAB = 6; +static constexpr int MIN_WINDOW_W = 120; +static constexpr int MIN_WINDOW_H = 80; + +struct Window; +using WindowDrawCallback = void (*)(Window* win, Framebuffer& fb); +using WindowMouseCallback = void (*)(Window* win, MouseEvent& ev); +using WindowKeyCallback = void (*)(Window* win, const Montauk::KeyEvent& key); +using WindowCloseCallback = void (*)(Window* win); +using WindowPollCallback = void (*)(Window* win); + +struct Window { + char title[MAX_TITLE_LEN]; + Rect frame; + WindowState state; + int z_order; + bool focused; + bool dirty; + + uint32_t* content; + int content_w, content_h; + + bool dragging; + int drag_offset_x, drag_offset_y; + + bool resizing; + ResizeEdge resize_edge; + Rect resize_start_frame; + int resize_start_mx, resize_start_my; + + Rect saved_frame; + + WindowDrawCallback on_draw; + WindowMouseCallback on_mouse; + WindowKeyCallback on_key; + WindowCloseCallback on_close; + WindowPollCallback on_poll; + void* app_data; + + bool external; // true = shared-memory window from external process + int ext_win_id; // window server ID (valid when external == true) + uint8_t ext_cursor; // cursor style requested by external app (0=arrow, 1=resize_h, 2=resize_v) + + Rect titlebar_rect() const { + return {frame.x, frame.y, frame.w, TITLEBAR_HEIGHT}; + } + + Rect content_rect() const { + return {frame.x + BORDER_WIDTH, frame.y + TITLEBAR_HEIGHT, + frame.w - 2 * BORDER_WIDTH, frame.h - TITLEBAR_HEIGHT - BORDER_WIDTH}; + } + + Rect close_btn_rect() const { + int by = frame.y + (TITLEBAR_HEIGHT - BTN_RADIUS * 2) / 2; + return {frame.x + 12, by, BTN_RADIUS * 2, BTN_RADIUS * 2}; + } + + Rect min_btn_rect() const { + int by = frame.y + (TITLEBAR_HEIGHT - BTN_RADIUS * 2) / 2; + return {frame.x + 12 + 22, by, BTN_RADIUS * 2, BTN_RADIUS * 2}; + } + + Rect max_btn_rect() const { + int by = frame.y + (TITLEBAR_HEIGHT - BTN_RADIUS * 2) / 2; + return {frame.x + 12 + 44, by, BTN_RADIUS * 2, BTN_RADIUS * 2}; + } +}; + +} // namespace gui diff --git a/template/sysroot/include/hresetintrin.h b/template/sysroot/include/hresetintrin.h new file mode 100644 index 0000000..d4817d0 --- /dev/null +++ b/template/sysroot/include/hresetintrin.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _HRESETINTRIN_H_INCLUDED +#define _HRESETINTRIN_H_INCLUDED + +#ifndef __HRESET__ +#pragma GCC push_options +#pragma GCC target ("hreset") +#define __DISABLE_HRESET__ +#endif /* __HRESET__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_hreset (unsigned int __EAX) +{ + __builtin_ia32_hreset (__EAX); +} + +#ifdef __DISABLE_HRESET__ +#undef __DISABLE_HRESET__ +#pragma GCC pop_options +#endif /* __DISABLE_HRESET__ */ +#endif /* _HRESETINTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/http/http.hpp b/template/sysroot/include/http/http.hpp new file mode 100644 index 0000000..8a10eb5 --- /dev/null +++ b/template/sysroot/include/http/http.hpp @@ -0,0 +1,316 @@ +/* + * http.hpp + * Simple HTTP request builder and response parser for MontaukOS + * Wraps tls::https_fetch() and raw sockets for ergonomic HTTP usage. + */ + +#pragma once + +#include +#include +#include +#include + +namespace http { + +// ---------------------------------------------------------------------------- +// Response +// ---------------------------------------------------------------------------- + +struct Response { + int status; // HTTP status code (200, 404, etc.) or -1 on error + const char* headers; // Pointer into raw buffer (header block) + int headers_len; + const char* body; // Pointer into raw buffer (body) + int body_len; + char* raw; // Owned buffer — caller must free with montauk::mfree() + int raw_len; +}; + +// Parse raw HTTP response in-place. Sets pointers into buf (does not copy). +// Returns status code, or -1 if unparseable. +inline int parse_response(char* buf, int len, Response* out) { + out->raw = buf; + out->raw_len = len; + out->status = -1; + out->headers = nullptr; + out->headers_len = 0; + out->body = nullptr; + out->body_len = 0; + + if (len < 12) return -1; // "HTTP/1.x NNN" + + // Parse status code from "HTTP/1.x NNN" + const char* p = buf; + while (*p && *p != ' ') p++; + if (*p != ' ') return -1; + p++; + int code = 0; + for (int i = 0; i < 3 && *p >= '0' && *p <= '9'; i++, p++) + code = code * 10 + (*p - '0'); + out->status = code; + + // Headers start after the status line + const char* hdr_start = buf; + while (hdr_start < buf + len - 1) { + if (*hdr_start == '\r' && *(hdr_start + 1) == '\n') { hdr_start += 2; break; } + if (*hdr_start == '\n') { hdr_start++; break; } + hdr_start++; + } + out->headers = hdr_start; + + // Find \r\n\r\n boundary between headers and body + for (const char* s = hdr_start; s < buf + len - 3; s++) { + if (s[0] == '\r' && s[1] == '\n' && s[2] == '\r' && s[3] == '\n') { + out->headers_len = (int)(s - hdr_start); + out->body = s + 4; + out->body_len = len - (int)(out->body - buf); + return code; + } + } + // No body separator found — entire remainder is headers + out->headers_len = len - (int)(hdr_start - buf); + return code; +} + +// Find a header value by name (case-insensitive match on the name). +// Writes value into out_val (up to max_len), returns true if found. +inline bool get_header(const Response* resp, const char* name, char* out_val, int max_len) { + if (!resp->headers || resp->headers_len == 0) return false; + int name_len = montauk::slen(name); + const char* p = resp->headers; + const char* end = resp->headers + resp->headers_len; + + while (p < end) { + // Case-insensitive prefix match + bool match = true; + if (p + name_len >= end) { match = false; } + else { + for (int i = 0; i < name_len; i++) { + char a = p[i], b = name[i]; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) { match = false; break; } + } + if (match && p[name_len] != ':') match = false; + } + + if (match) { + const char* v = p + name_len + 1; + while (v < end && *v == ' ') v++; // skip OWS + int i = 0; + while (v < end && *v != '\r' && *v != '\n' && i < max_len - 1) + out_val[i++] = *v++; + out_val[i] = 0; + return true; + } + + // Skip to next line + while (p < end && *p != '\n') p++; + if (p < end) p++; + } + return false; +} + +// Free a response's raw buffer. +inline void free_response(Response* resp) { + if (resp->raw) { montauk::mfree(resp->raw); resp->raw = nullptr; } +} + +// ---------------------------------------------------------------------------- +// Request builder (internal) +// ---------------------------------------------------------------------------- + +inline int build_request(char* buf, int buf_size, + const char* method, const char* host, + const char* path, const char* content_type, + const char* body_data, int body_len, + const char* extra_headers) { + char* p = buf; + char* end = buf + buf_size - 1; + + auto append = [&](const char* s) { + while (*s && p < end) *p++ = *s++; + }; + auto append_int = [&](int n) { + char tmp[16]; int ti = 0; + if (n == 0) { if (p < end) *p++ = '0'; return; } + while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; } + for (int j = ti - 1; j >= 0 && p < end; j--) *p++ = tmp[j]; + }; + + // Request line + append(method); append(" "); append(path); append(" HTTP/1.1\r\n"); + + // Host + append("Host: "); append(host); append("\r\n"); + + // Content headers (for POST/PUT/PATCH) + if (body_data && body_len > 0) { + if (content_type) { + append("Content-Type: "); append(content_type); append("\r\n"); + } + append("Content-Length: "); append_int(body_len); append("\r\n"); + } + + // Extra headers (caller-supplied, must include \r\n terminators) + if (extra_headers) append(extra_headers); + + append("Connection: close\r\n"); + append("\r\n"); + + int header_len = (int)(p - buf); + + // Append body + if (body_data && body_len > 0 && header_len + body_len < buf_size) { + montauk::memcpy(p, body_data, body_len); + p += body_len; + } + + return (int)(p - buf); +} + +// ---------------------------------------------------------------------------- +// Public API +// ---------------------------------------------------------------------------- + +// GET request over HTTPS. Returns parsed response. Caller must free_response(). +inline Response get(const char* host, const char* path, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + char req[1024]; + int reqLen = build_request(req, sizeof(req), "GET", host, path, + nullptr, nullptr, 0, extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) return resp; + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// POST request over HTTPS. Returns parsed response. Caller must free_response(). +inline Response post(const char* host, const char* path, + const char* content_type, + const char* body_data, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + int req_size = 1024 + body_len; + char* req = (char*)montauk::malloc(req_size); + if (!req) return resp; + + int reqLen = build_request(req, req_size, "POST", host, path, + content_type, body_data, body_len, + extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::mfree(req); return resp; } + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + montauk::mfree(req); + + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// Generic request over HTTPS (PUT, PATCH, DELETE, etc.). +inline Response request(const char* method, + const char* host, const char* path, + const char* content_type, + const char* body_data, int body_len, + const tls::TrustAnchors& tas, + int resp_buf_size = 32768, + const char* extra_headers = nullptr, + tls::AbortCheckFn abort_check = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + int req_size = 1024 + (body_len > 0 ? body_len : 0); + char* req = (char*)montauk::malloc(req_size); + if (!req) return resp; + + int reqLen = build_request(req, req_size, method, host, path, + content_type, body_data, body_len, + extra_headers); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::mfree(req); return resp; } + + int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, + buf, resp_buf_size - 1, abort_check); + montauk::mfree(req); + + if (n <= 0) { montauk::mfree(buf); return resp; } + buf[n] = 0; + + parse_response(buf, n, &resp); + return resp; +} + +// Plain HTTP (no TLS) GET over port 80. +inline Response get_plain(const char* host, const char* path, + int resp_buf_size = 32768, + const char* extra_headers = nullptr) { + Response resp = {}; + resp.status = -1; + + uint32_t ip = montauk::resolve(host); + if (!ip) return resp; + + char req[1024]; + int reqLen = build_request(req, sizeof(req), "GET", host, path, + nullptr, nullptr, 0, extra_headers); + + int sock = montauk::socket(Montauk::SOCK_TCP); + if (sock < 0) return resp; + if (montauk::connect(sock, ip, 80) < 0) { montauk::closesocket(sock); return resp; } + + montauk::send(sock, req, reqLen); + + char* buf = (char*)montauk::malloc(resp_buf_size); + if (!buf) { montauk::closesocket(sock); return resp; } + + int total = 0; + while (total < resp_buf_size - 1) { + int n = montauk::recv(sock, buf + total, resp_buf_size - 1 - total); + if (n <= 0) break; + total += n; + } + montauk::closesocket(sock); + + if (total <= 0) { montauk::mfree(buf); return resp; } + buf[total] = 0; + + parse_response(buf, total, &resp); + return resp; +} + +} // namespace http diff --git a/template/sysroot/include/ia32intrin.h b/template/sysroot/include/ia32intrin.h new file mode 100644 index 0000000..47d561e --- /dev/null +++ b/template/sysroot/include/ia32intrin.h @@ -0,0 +1,317 @@ +/* Copyright (C) 2009-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +/* 32bit bsf */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bsfd (int __X) +{ + return __builtin_ctz (__X); +} + +/* 32bit bsr */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bsrd (int __X) +{ + return __builtin_ia32_bsrsi (__X); +} + +/* 32bit bswap */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bswapd (int __X) +{ + return __builtin_bswap32 (__X); +} + +#ifndef __iamcu__ + +#ifndef __CRC32__ +#pragma GCC push_options +#pragma GCC target("crc32") +#define __DISABLE_CRC32__ +#endif /* __CRC32__ */ + +/* 32bit accumulate CRC32 (polynomial 0x11EDC6F41) value. */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__crc32b (unsigned int __C, unsigned char __V) +{ + return __builtin_ia32_crc32qi (__C, __V); +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__crc32w (unsigned int __C, unsigned short __V) +{ + return __builtin_ia32_crc32hi (__C, __V); +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__crc32d (unsigned int __C, unsigned int __V) +{ + return __builtin_ia32_crc32si (__C, __V); +} + +#ifdef __DISABLE_CRC32__ +#undef __DISABLE_CRC32__ +#pragma GCC pop_options +#endif /* __DISABLE_CRC32__ */ + +#endif /* __iamcu__ */ + +/* 32bit popcnt */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__popcntd (unsigned int __X) +{ + return __builtin_popcount (__X); +} + +#ifndef __iamcu__ + +/* rdpmc */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rdpmc (int __S) +{ + return __builtin_ia32_rdpmc (__S); +} + +#endif /* __iamcu__ */ + +/* rdtsc */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rdtsc (void) +{ + return __builtin_ia32_rdtsc (); +} + +#ifndef __iamcu__ + +/* rdtscp */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rdtscp (unsigned int *__A) +{ + return __builtin_ia32_rdtscp (__A); +} + +#endif /* __iamcu__ */ + +/* 8bit rol */ +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rolb (unsigned char __X, int __C) +{ + return __builtin_ia32_rolqi (__X, __C); +} + +/* 16bit rol */ +extern __inline unsigned short +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rolw (unsigned short __X, int __C) +{ + return __builtin_ia32_rolhi (__X, __C); +} + +/* 32bit rol */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rold (unsigned int __X, int __C) +{ + __C &= 31; + return (__X << __C) | (__X >> (-__C & 31)); +} + +/* 8bit ror */ +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rorb (unsigned char __X, int __C) +{ + return __builtin_ia32_rorqi (__X, __C); +} + +/* 16bit ror */ +extern __inline unsigned short +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rorw (unsigned short __X, int __C) +{ + return __builtin_ia32_rorhi (__X, __C); +} + +/* 32bit ror */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rord (unsigned int __X, int __C) +{ + __C &= 31; + return (__X >> __C) | (__X << (-__C & 31)); +} + +/* Pause */ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__pause (void) +{ + __builtin_ia32_pause (); +} + +#ifdef __x86_64__ +/* 64bit bsf */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bsfq (long long __X) +{ + return __builtin_ctzll (__X); +} + +/* 64bit bsr */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bsrq (long long __X) +{ + return __builtin_ia32_bsrdi (__X); +} + +/* 64bit bswap */ +extern __inline long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bswapq (long long __X) +{ + return __builtin_bswap64 (__X); +} + +#ifndef __CRC32__ +#pragma GCC push_options +#pragma GCC target("crc32") +#define __DISABLE_CRC32__ +#endif /* __CRC32__ */ + +/* 64bit accumulate CRC32 (polynomial 0x11EDC6F41) value. */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__crc32q (unsigned long long __C, unsigned long long __V) +{ + return __builtin_ia32_crc32di (__C, __V); +} + +#ifdef __DISABLE_CRC32__ +#undef __DISABLE_CRC32__ +#pragma GCC pop_options +#endif /* __DISABLE_CRC32__ */ + +/* 64bit popcnt */ +extern __inline long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__popcntq (unsigned long long __X) +{ + return __builtin_popcountll (__X); +} + +/* 64bit rol */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rolq (unsigned long long __X, int __C) +{ + __C &= 63; + return (__X << __C) | (__X >> (-__C & 63)); +} + +/* 64bit ror */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__rorq (unsigned long long __X, int __C) +{ + __C &= 63; + return (__X >> __C) | (__X << (-__C & 63)); +} + +/* Read flags register */ +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__readeflags (void) +{ + return __builtin_ia32_readeflags_u64 (); +} + +/* Write flags register */ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__writeeflags (unsigned long long __X) +{ + __builtin_ia32_writeeflags_u64 (__X); +} + +#define _bswap64(a) __bswapq(a) +#define _popcnt64(a) __popcntq(a) +#else + +/* Read flags register */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__readeflags (void) +{ + return __builtin_ia32_readeflags_u32 (); +} + +/* Write flags register */ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__writeeflags (unsigned int __X) +{ + __builtin_ia32_writeeflags_u32 (__X); +} + +#endif + +/* On LP64 systems, longs are 64-bit. Use the appropriate rotate + * function. */ +#ifdef __LP64__ +#define _lrotl(a,b) __rolq((a), (b)) +#define _lrotr(a,b) __rorq((a), (b)) +#else +#define _lrotl(a,b) __rold((a), (b)) +#define _lrotr(a,b) __rord((a), (b)) +#endif + +#define _bit_scan_forward(a) __bsfd(a) +#define _bit_scan_reverse(a) __bsrd(a) +#define _bswap(a) __bswapd(a) +#define _popcnt32(a) __popcntd(a) +#ifndef __iamcu__ +#define _rdpmc(a) __rdpmc(a) +#define _rdtscp(a) __rdtscp(a) +#endif /* __iamcu__ */ +#define _rdtsc() __rdtsc() +#define _rotwl(a,b) __rolw((a), (b)) +#define _rotwr(a,b) __rorw((a), (b)) +#define _rotl(a,b) __rold((a), (b)) +#define _rotr(a,b) __rord((a), (b)) diff --git a/template/sysroot/include/immintrin.h b/template/sysroot/include/immintrin.h new file mode 100644 index 0000000..b4243dd --- /dev/null +++ b/template/sysroot/include/immintrin.h @@ -0,0 +1,149 @@ +/* Copyright (C) 2008-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#define _IMMINTRIN_H_INCLUDED + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#endif /* _IMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/initializer_list b/template/sysroot/include/initializer_list new file mode 100644 index 0000000..91b609c --- /dev/null +++ b/template/sysroot/include/initializer_list @@ -0,0 +1,105 @@ +// std::initializer_list support -*- C++ -*- + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file initializer_list + * This is a Standard C++ Library header. + */ + +#ifndef _INITIALIZER_LIST +#define _INITIALIZER_LIST + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else // C++0x + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ + /// initializer_list + template + class initializer_list + { + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + typedef const _E* iterator; + typedef const _E* const_iterator; + + private: + iterator _M_array; + size_type _M_len; + + // The compiler can call a private constructor. + constexpr initializer_list(const_iterator __a, size_type __l) + : _M_array(__a), _M_len(__l) { } + + public: + constexpr initializer_list() noexcept + : _M_array(0), _M_len(0) { } + + // Number of elements. + constexpr size_type + size() const noexcept { return _M_len; } + + // First element. + constexpr const_iterator + begin() const noexcept { return _M_array; } + + // One past the last element. + constexpr const_iterator + end() const noexcept { return begin() + size(); } + }; + + /** + * @brief Return an iterator pointing to the first element of + * the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + begin(initializer_list<_Tp> __ils) noexcept + { return __ils.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element + * of the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + end(initializer_list<_Tp> __ils) noexcept + { return __ils.end(); } +} + +#endif // C++11 + +#endif // _INITIALIZER_LIST diff --git a/template/sysroot/include/iso646.h b/template/sysroot/include/iso646.h new file mode 100644 index 0000000..e61b06d --- /dev/null +++ b/template/sysroot/include/iso646.h @@ -0,0 +1,45 @@ +/* Copyright (C) 1997-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.9 Alternative spellings + */ + +#ifndef _ISO646_H +#define _ISO646_H + +#ifndef __cplusplus +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= +#endif + +#endif diff --git a/template/sysroot/include/iterator b/template/sysroot/include/iterator new file mode 100644 index 0000000..b3a3c35 --- /dev/null +++ b/template/sysroot/include/iterator @@ -0,0 +1,84 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/iterator + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ITERATOR +#define _GLIBCXX_ITERATOR 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#if _GLIBCXX_HOSTED +# include +# include +#endif +#include + +#define __glibcxx_want_array_constexpr +#define __glibcxx_want_constexpr_iterator +#define __glibcxx_want_make_reverse_iterator +#define __glibcxx_want_move_iterator_concept +#define __glibcxx_want_nonmember_container_access +#define __glibcxx_want_null_iterators +#define __glibcxx_want_ranges +#define __glibcxx_want_ssize +#include + +#if __cplusplus >= 202002L +#include // ranges::distance, ranges::next, ranges::prev +#endif + +#endif /* _GLIBCXX_ITERATOR */ diff --git a/template/sysroot/include/keylockerintrin.h b/template/sysroot/include/keylockerintrin.h new file mode 100644 index 0000000..37e0943 --- /dev/null +++ b/template/sysroot/include/keylockerintrin.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _KEYLOCKERINTRIN_H_INCLUDED +#define _KEYLOCKERINTRIN_H_INCLUDED + +#ifndef __KL__ +#pragma GCC push_options +#pragma GCC target("kl") +#define __DISABLE_KL__ +#endif /* __KL__ */ + + +extern __inline +void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadiwkey (unsigned int __I, __m128i __A, __m128i __B, __m128i __C) +{ + __builtin_ia32_loadiwkey ((__v2di) __B, (__v2di) __C, (__v2di) __A, __I); +} + +extern __inline +unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_encodekey128_u32 (unsigned int __I, __m128i __A, void * __P) +{ + return __builtin_ia32_encodekey128_u32 (__I, (__v2di)__A, __P); +} + +extern __inline +unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_encodekey256_u32 (unsigned int __I, __m128i __A, __m128i __B, void * __P) +{ + return __builtin_ia32_encodekey256_u32 (__I, (__v2di)__A, (__v2di)__B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesdec128kl_u8 (__m128i * __A, __m128i __B, const void * __P) +{ + return __builtin_ia32_aesdec128kl_u8 ((__v2di *) __A, (__v2di) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesdec256kl_u8 (__m128i * __A, __m128i __B, const void * __P) +{ + return __builtin_ia32_aesdec256kl_u8 ((__v2di *) __A, (__v2di) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesenc128kl_u8 (__m128i * __A, __m128i __B, const void * __P) +{ + return __builtin_ia32_aesenc128kl_u8 ((__v2di *) __A, (__v2di) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesenc256kl_u8 (__m128i * __A, __m128i __B, const void * __P) +{ + return __builtin_ia32_aesenc256kl_u8 ((__v2di *) __A, (__v2di) __B, __P); +} + +#ifdef __DISABLE_KL__ +#undef __DISABLE_KL__ +#pragma GCC pop_options +#endif /* __DISABLE_KL__ */ + +#ifndef __WIDEKL__ +#pragma GCC push_options +#pragma GCC target("widekl") +#define __DISABLE_WIDEKL__ +#endif /* __WIDEKL__ */ + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesdecwide128kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P) +{ + return __builtin_ia32_aesdecwide128kl_u8 ((__v2di *) __A, (__v2di *) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesdecwide256kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P) +{ + return __builtin_ia32_aesdecwide256kl_u8 ((__v2di *) __A, (__v2di *) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesencwide128kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P) +{ + return __builtin_ia32_aesencwide128kl_u8 ((__v2di *) __A, (__v2di *) __B, __P); +} + +extern __inline +unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesencwide256kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P) +{ + return __builtin_ia32_aesencwide256kl_u8 ((__v2di *) __A, (__v2di *) __B, __P); +} +#ifdef __DISABLE_WIDEKL__ +#undef __DISABLE_WIDEKL__ +#pragma GCC pop_options +#endif /* __DISABLE_WIDEKL__ */ +#endif /* _KEYLOCKERINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/libc/assert.h b/template/sysroot/include/libc/assert.h new file mode 100644 index 0000000..b1f703e --- /dev/null +++ b/template/sysroot/include/libc/assert.h @@ -0,0 +1,23 @@ +#ifndef _LIBC_ASSERT_H +#define _LIBC_ASSERT_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void __assert_fail(const char *expr, const char *file, int line, const char *func); + +#ifdef NDEBUG +#define assert(expr) ((void)0) +#else +#define assert(expr) \ + ((expr) ? (void)0 : __assert_fail(#expr, __FILE__, __LINE__, __func__)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_ASSERT_H */ diff --git a/template/sysroot/include/libc/ctype.h b/template/sysroot/include/libc/ctype.h new file mode 100644 index 0000000..efca6ed --- /dev/null +++ b/template/sysroot/include/libc/ctype.h @@ -0,0 +1,28 @@ +#ifndef _LIBC_CTYPE_H +#define _LIBC_CTYPE_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +int isalpha(int c); +int isdigit(int c); +int isalnum(int c); +int isspace(int c); +int isupper(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isxdigit(int c); +int iscntrl(int c); +int isgraph(int c); +int toupper(int c); +int tolower(int c); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_CTYPE_H */ diff --git a/template/sysroot/include/libc/errno.h b/template/sysroot/include/libc/errno.h new file mode 100644 index 0000000..cdbda4d --- /dev/null +++ b/template/sysroot/include/libc/errno.h @@ -0,0 +1,29 @@ +#ifndef _LIBC_ERRNO_H +#define _LIBC_ERRNO_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern int errno; + +#define ENOENT 2 +#define EIO 5 +#define ENOMEM 12 +#define EACCES 13 +#define EINVAL 22 +#define ERANGE 34 +#define ENOSYS 38 +#define EISDIR 21 +#define ENOTDIR 20 +#define EEXIST 17 +#define EBADF 9 +#define EPERM 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_ERRNO_H */ diff --git a/template/sysroot/include/libc/fcntl.h b/template/sysroot/include/libc/fcntl.h new file mode 100644 index 0000000..46890eb --- /dev/null +++ b/template/sysroot/include/libc/fcntl.h @@ -0,0 +1,22 @@ +#ifndef _LIBC_FCNTL_H +#define _LIBC_FCNTL_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 0x40 +#define O_TRUNC 0x200 + +int open(const char *path, int flags, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_FCNTL_H */ diff --git a/template/sysroot/include/libc/inttypes.h b/template/sysroot/include/libc/inttypes.h new file mode 100644 index 0000000..398a5fc --- /dev/null +++ b/template/sysroot/include/libc/inttypes.h @@ -0,0 +1,27 @@ +#ifndef _LIBC_INTTYPES_H +#define _LIBC_INTTYPES_H + +#include + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "ld" +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "li" +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "lu" +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "lx" +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "lX" + +#endif /* _LIBC_INTTYPES_H */ diff --git a/template/sysroot/include/libc/limits.h b/template/sysroot/include/libc/limits.h new file mode 100644 index 0000000..c9e9c6b --- /dev/null +++ b/template/sysroot/include/libc/limits.h @@ -0,0 +1,31 @@ +#ifndef _LIBC_LIMITS_H +#define _LIBC_LIMITS_H + +#pragma once + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 + +#define INT_MIN (-2147483647 - 1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +#define LONG_MIN (-9223372036854775807L - 1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL + +#define LLONG_MIN (-9223372036854775807LL - 1) +#define LLONG_MAX 9223372036854775807LL +#define ULLONG_MAX 18446744073709551615ULL + +#define PATH_MAX 4096 +#define NAME_MAX 256 + +#endif /* _LIBC_LIMITS_H */ diff --git a/template/sysroot/include/libc/math.h b/template/sysroot/include/libc/math.h new file mode 100644 index 0000000..b4522b2 --- /dev/null +++ b/template/sysroot/include/libc/math.h @@ -0,0 +1,31 @@ +#ifndef _LIBC_MATH_H +#define _LIBC_MATH_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define HUGE_VAL __builtin_huge_val() +#define INFINITY __builtin_inff() +#define NAN __builtin_nanf("") + +double fabs(double x); +double floor(double x); +double ceil(double x); +double sqrt(double x); +double sin(double x); +double cos(double x); +double atan2(double y, double x); +double pow(double base, double exp); +double log(double x); +double exp(double x); +double fmod(double x, double y); +double round(double x); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_MATH_H */ diff --git a/template/sysroot/include/libc/stdio.h b/template/sysroot/include/libc/stdio.h new file mode 100644 index 0000000..93bb94b --- /dev/null +++ b/template/sysroot/include/libc/stdio.h @@ -0,0 +1,77 @@ +#ifndef _LIBC_STDIO_H +#define _LIBC_STDIO_H + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define EOF (-1) +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#define BUFSIZ 1024 +#define FILENAME_MAX 256 + +typedef struct _FILE { + int handle; + unsigned long pos; + unsigned long size; + int eof; + int error; + int is_std; + int ungetc_buf; +} FILE; + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; + +int printf(const char *fmt, ...); +int fprintf(FILE *stream, const char *fmt, ...); +int sprintf(char *str, const char *fmt, ...); +int snprintf(char *str, size_t size, const char *fmt, ...); +int vprintf(const char *fmt, va_list ap); +int vfprintf(FILE *stream, const char *fmt, va_list ap); +int vsprintf(char *str, const char *fmt, va_list ap); +int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); + +int puts(const char *s); +int putchar(int c); + +FILE *fopen(const char *path, const char *mode); +int fclose(FILE *stream); +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +int fseek(FILE *stream, long offset, int whence); +long ftell(FILE *stream); +int fflush(FILE *stream); + +int rename(const char *oldpath, const char *newpath); +int remove(const char *path); + +int sscanf(const char *str, const char *fmt, ...); + +int feof(FILE *stream); +int ferror(FILE *stream); +void clearerr(FILE *stream); + +int fgetc(FILE *stream); +int getc(FILE *stream); +int ungetc(int c, FILE *stream); +char *fgets(char *s, int size, FILE *stream); +int fputs(const char *s, FILE *stream); + +void perror(const char *s); +FILE *tmpfile(void); +char *tmpnam(char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_STDIO_H */ diff --git a/template/sysroot/include/libc/stdlib.h b/template/sysroot/include/libc/stdlib.h new file mode 100644 index 0000000..0ffaf2a --- /dev/null +++ b/template/sysroot/include/libc/stdlib.h @@ -0,0 +1,66 @@ +#ifndef _LIBC_STDLIB_H +#define _LIBC_STDLIB_H + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#define RAND_MAX 0x7fffffff + +typedef struct { + int quot; + int rem; +} div_t; + +typedef struct { + long quot; + long rem; +} ldiv_t; + +void *malloc(size_t size); +void free(void *ptr); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *ptr, size_t size); + +int atoi(const char *s); +long atol(const char *s); +double atof(const char *s); + +int abs(int j); +long labs(long j); + +void exit(int status); +void abort(void); +int atexit(void (*func)(void)); + +char *getenv(const char *name); + +void qsort(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *)); + +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); + +int rand(void); +void srand(unsigned int seed); + +div_t div(int numer, int denom); +ldiv_t ldiv(long numer, long denom); + +int system(const char *command); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_STDLIB_H */ diff --git a/template/sysroot/include/libc/string.h b/template/sysroot/include/libc/string.h new file mode 100644 index 0000000..77542ee --- /dev/null +++ b/template/sysroot/include/libc/string.h @@ -0,0 +1,36 @@ +#ifndef _LIBC_STRING_H +#define _LIBC_STRING_H + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *memcpy(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); +void *memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +void *memchr(const void *s, int c, size_t n); + +size_t strlen(const char *s); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, size_t n); +char *strdup(const char *s); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); +char *strstr(const char *haystack, const char *needle); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_STRING_H */ diff --git a/template/sysroot/include/libc/strings.h b/template/sysroot/include/libc/strings.h new file mode 100644 index 0000000..fba3df7 --- /dev/null +++ b/template/sysroot/include/libc/strings.h @@ -0,0 +1,17 @@ +#ifndef _LIBC_STRINGS_H +#define _LIBC_STRINGS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_STRINGS_H */ diff --git a/template/sysroot/include/libc/sys/stat.h b/template/sysroot/include/libc/sys/stat.h new file mode 100644 index 0000000..e0f9f5b --- /dev/null +++ b/template/sysroot/include/libc/sys/stat.h @@ -0,0 +1,24 @@ +#ifndef _LIBC_SYS_STAT_H +#define _LIBC_SYS_STAT_H + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct stat { + unsigned long st_size; +}; + +int mkdir(const char *path, unsigned int mode); +int stat(const char *path, struct stat *buf); +int fstat(int fd, struct stat *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_SYS_STAT_H */ diff --git a/template/sysroot/include/libc/sys/time.h b/template/sysroot/include/libc/sys/time.h new file mode 100644 index 0000000..6deee02 --- /dev/null +++ b/template/sysroot/include/libc/sys/time.h @@ -0,0 +1,24 @@ +#ifndef _LIBC_SYS_TIME_H +#define _LIBC_SYS_TIME_H + +/* Stub header for MontaukOS */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct timeval { + long tv_sec; + long tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_SYS_TIME_H */ diff --git a/template/sysroot/include/libc/sys/types.h b/template/sysroot/include/libc/sys/types.h new file mode 100644 index 0000000..350e0fb --- /dev/null +++ b/template/sysroot/include/libc/sys/types.h @@ -0,0 +1,23 @@ +#ifndef _LIBC_SYS_TYPES_H +#define _LIBC_SYS_TYPES_H + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long size_t; +typedef long ssize_t; +typedef long off_t; +typedef int pid_t; +typedef unsigned int mode_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; +typedef long time_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_SYS_TYPES_H */ diff --git a/template/sysroot/include/libc/unistd.h b/template/sysroot/include/libc/unistd.h new file mode 100644 index 0000000..fe56976 --- /dev/null +++ b/template/sysroot/include/libc/unistd.h @@ -0,0 +1,20 @@ +#ifndef _LIBC_UNISTD_H +#define _LIBC_UNISTD_H + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int read(int fd, void *buf, size_t count); +int write(int fd, const void *buf, size_t count); +int close(int fd); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBC_UNISTD_H */ diff --git a/template/sysroot/include/limits b/template/sysroot/include/limits new file mode 100644 index 0000000..44a5ff3 --- /dev/null +++ b/template/sysroot/include/limits @@ -0,0 +1,2240 @@ +// The template and inlines for the numeric_limits classes. -*- C++ -*- + +// Copyright (C) 1999-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/limits + * This is a Standard C++ Library header. + */ + +// Note: this is not a conforming implementation. +// Written by Gabriel Dos Reis + +// +// ISO 14882:1998 +// 18.2.1 +// + +#ifndef _GLIBCXX_NUMERIC_LIMITS +#define _GLIBCXX_NUMERIC_LIMITS 1 + +#pragma GCC system_header + +#include + +// +// The numeric_limits<> traits document implementation-defined aspects +// of fundamental arithmetic data types (integers and floating points). +// From Standard C++ point of view, there are 14 such types: +// * integers +// bool (1) +// char, signed char, unsigned char, wchar_t (4) +// short, unsigned short (2) +// int, unsigned (2) +// long, unsigned long (2) +// +// * floating points +// float (1) +// double (1) +// long double (1) +// +// GNU C++ understands (where supported by the host C-library) +// * integer +// long long, unsigned long long (2) +// +// which brings us to 16 fundamental arithmetic data types in GNU C++. +// +// +// Since a numeric_limits<> is a bit tricky to get right, we rely on +// an interface composed of macros which should be defined in config/os +// or config/cpu when they differ from the generic (read arbitrary) +// definitions given here. +// + +// These values can be overridden in the target configuration file. +// The default values are appropriate for many 32-bit targets. + +// GCC only intrinsically supports modulo integral types. The only remaining +// integral exceptional values is division by zero. Only targets that do not +// signal division by zero in some "hard to ignore" way should use false. +#ifndef __glibcxx_integral_traps +# define __glibcxx_integral_traps true +#endif + +// float +// + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_float_has_denorm_loss +# define __glibcxx_float_has_denorm_loss false +#endif +#ifndef __glibcxx_float_traps +# define __glibcxx_float_traps false +#endif +#ifndef __glibcxx_float_tinyness_before +# define __glibcxx_float_tinyness_before false +#endif + +// double + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_double_has_denorm_loss +# define __glibcxx_double_has_denorm_loss false +#endif +#ifndef __glibcxx_double_traps +# define __glibcxx_double_traps false +#endif +#ifndef __glibcxx_double_tinyness_before +# define __glibcxx_double_tinyness_before false +#endif + +// long double + +// Default values. Should be overridden in configuration files if necessary. + +#if !(defined(__clang__) && !__STDC_HOSTED__) // clang in kernel context + +#ifndef __glibcxx_long_double_has_denorm_loss +# define __glibcxx_long_double_has_denorm_loss false +#endif +#ifndef __glibcxx_long_double_traps +# define __glibcxx_long_double_traps false +#endif +#ifndef __glibcxx_long_double_tinyness_before +# define __glibcxx_long_double_tinyness_before false +#endif + +#endif + +// You should not need to define any macros below this point. + +#define __glibcxx_signed_b(T,B) ((T)(-1) < 0) + +#define __glibcxx_min_b(T,B) \ + (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0) + +#define __glibcxx_max_b(T,B) \ + (__glibcxx_signed_b (T,B) ? \ + (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0) + +#define __glibcxx_digits_b(T,B) \ + (B - __glibcxx_signed_b (T,B)) + +// The fraction 643/2136 approximates log10(2) to 7 significant digits. +#define __glibcxx_digits10_b(T,B) \ + (__glibcxx_digits_b (T,B) * 643L / 2136) + +#define __glibcxx_signed(T) \ + __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_min(T) \ + __glibcxx_min_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_max(T) \ + __glibcxx_max_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits(T) \ + __glibcxx_digits_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits10(T) \ + __glibcxx_digits10_b (T, sizeof(T) * __CHAR_BIT__) + +#define __glibcxx_max_digits10(T) \ + (2 + (T) * 643L / 2136) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Describes the rounding style for floating-point types. + * + * This is used in the std::numeric_limits class. + */ + enum float_round_style + { + round_indeterminate = -1, ///< Intermediate. + round_toward_zero = 0, ///< To zero. + round_to_nearest = 1, ///< To the nearest representable value. + round_toward_infinity = 2, ///< To infinity. + round_toward_neg_infinity = 3 ///< To negative infinity. + }; + + /** + * @brief Describes the denormalization for floating-point types. + * + * These values represent the presence or absence of a variable number + * of exponent bits. This type is used in the std::numeric_limits class. + */ + enum float_denorm_style + { + /// Indeterminate at compile time whether denormalized values are allowed. + denorm_indeterminate = -1, + /// The type does not allow denormalized values. + denorm_absent = 0, + /// The type allows denormalized values. + denorm_present = 1 + }; + + /** + * @brief Part of std::numeric_limits. + * + * The @c static @c const members are usable as integral constant + * expressions. + * + * @note This is a separate class for purposes of efficiency; you + * should only access these members as part of an instantiation + * of the std::numeric_limits class. + */ + struct __numeric_limits_base + { + /** This will be true for all fundamental types (which have + specializations), and false for everything else. */ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = false; + + /** The number of @c radix digits that be represented without change: for + integer types, the number of non-sign bits in the mantissa; for + floating types, the number of @c radix digits in the mantissa. */ + static _GLIBCXX_USE_CONSTEXPR int digits = 0; + + /** The number of base 10 digits that can be represented without change. */ + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; + +#if __cplusplus >= 201103L + /** The number of base 10 digits required to ensure that values which + differ are always differentiated. */ + static constexpr int max_digits10 = 0; +#endif + + /** True if the type is signed. */ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + + /** True if the type is integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + + /** True if the type uses an exact representation. All integer types are + exact, but not all exact types are integer. For example, rational and + fixed-exponent representations are exact but not integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + + /** For integer types, specifies the base of the representation. For + floating types, specifies the base of the exponent representation. */ + static _GLIBCXX_USE_CONSTEXPR int radix = 0; + + /** The minimum negative integer such that @c radix raised to the power of + (one less than that integer) is a normalized floating point number. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + + /** The minimum negative integer such that 10 raised to that power is in + the range of normalized floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + + /** The maximum positive integer such that @c radix raised to the power of + (one less than that integer) is a representable finite floating point + number. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + + /** The maximum positive integer such that 10 raised to that power is in + the range of representable finite floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + /** True if the type has a representation for positive infinity. */ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + + /** True if the type has a representation for a quiet (non-signaling) + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + + /** True if the type has a representation for a signaling + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + + /** See std::float_denorm_style for more information. */ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + + /** True if loss of accuracy is detected as a denormalization loss, + rather than as an inexact result. */ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + /** True if-and-only-if the type adheres to the IEC 559 standard, also + known as IEEE 754. (Only makes sense for floating point types.) */ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + + /** True if the set of values representable by the type is + finite. All built-in types are bounded, this member would be + false for arbitrary precision types. */ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = false; + + /** True if the type is @e modulo. A type is modulo if, for any + operation involving +, -, or * on values of that type whose + result would fall outside the range [min(),max()], the value + returned differs from the true value by an integer multiple of + max() - min() + 1. On most machines, this is false for floating + types, true for unsigned integers, and true for signed integers. + See PR22200 about signed integers. */ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + /** True if trapping is implemented for this type. */ + static _GLIBCXX_USE_CONSTEXPR bool traps = false; + + /** True if tininess is detected before rounding. (see IEC 559) */ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + + /** See std::float_round_style for more information. This is only + meaningful for floating types; integer types will all be + round_toward_zero. */ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_toward_zero; + }; + + /** + * @brief Properties of fundamental types. + * + * This class allows a program to obtain information about the + * representation of a fundamental type on a given platform. For + * non-fundamental types, the functions will return 0 and the data + * members will all be @c false. + */ + template + struct numeric_limits : public __numeric_limits_base + { + /** The minimum finite value, or for floating types with + denormalization, the minimum positive normalized value. */ + static _GLIBCXX_CONSTEXPR _Tp + min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum finite value. */ + static _GLIBCXX_CONSTEXPR _Tp + max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + +#if __cplusplus >= 201103L + /** A finite value x such that there is no other finite value y + * where y < x. */ + static constexpr _Tp + lowest() noexcept { return _Tp(); } +#endif + + /** The @e machine @e epsilon: the difference between 1 and the least + value greater than 1 that is representable. */ + static _GLIBCXX_CONSTEXPR _Tp + epsilon() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum rounding error measurement (see LIA-1). */ + static _GLIBCXX_CONSTEXPR _Tp + round_error() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of positive infinity, if @c has_infinity. */ + static _GLIBCXX_CONSTEXPR _Tp + infinity() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a quiet Not a Number, + if @c has_quiet_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a signaling Not a Number, if + @c has_signaling_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The minimum positive denormalized value. For types where + @c has_denorm is false, this is the minimum positive normalized + value. */ + static _GLIBCXX_CONSTEXPR _Tp + denorm_min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 559. numeric_limits + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + // Now there follow 16 explicit specializations. Yes, 16. Make sure + // you get the count right. (18 in C++11 mode, with char16_t and char32_t.) + // (+1 if char8_t is enabled.) + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 184. numeric_limits wording problems + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR bool + min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + max() _GLIBCXX_USE_NOEXCEPT { return true; } + +#if __cplusplus >= 201103L + static constexpr bool + lowest() noexcept { return min(); } +#endif + static _GLIBCXX_USE_CONSTEXPR int digits = 1; + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR bool + epsilon() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + round_error() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR bool + infinity() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + denorm_min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + // It is not clear what it means for a boolean type to trap. + // This is a DR on the LWG issue list. Here, I use integer + // promotion semantics. + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min(char); } + + static _GLIBCXX_CONSTEXPR char + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max(char); } + +#if __cplusplus >= 201103L + static constexpr char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR + char infinity() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR signed char + min() _GLIBCXX_USE_NOEXCEPT { return -__SCHAR_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR signed char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__; } + +#if __cplusplus >= 201103L + static constexpr signed char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (signed char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (signed char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR signed char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR signed char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR signed char + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned char + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned char + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR wchar_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (wchar_t); } + + static _GLIBCXX_CONSTEXPR wchar_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (wchar_t); } + +#if __cplusplus >= 201103L + static constexpr wchar_t + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (wchar_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (wchar_t); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (wchar_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR wchar_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR wchar_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR wchar_t + infinity() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#if _GLIBCXX_USE_CHAR8_T + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char8_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + lowest() _GLIBCXX_USE_NOEXCEPT { return min(); } + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t); + static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0; + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char8_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char8_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR char8_t + infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; +#endif + +#if __cplusplus >= 201103L + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char16_t + min() noexcept { return __glibcxx_min (char16_t); } + + static constexpr char16_t + max() noexcept { return __glibcxx_max (char16_t); } + + static constexpr char16_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char16_t); + static constexpr int digits10 = __glibcxx_digits10 (char16_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char16_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char16_t + epsilon() noexcept { return 0; } + + static constexpr char16_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char16_t + infinity() noexcept { return char16_t(); } + + static constexpr char16_t + quiet_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + signaling_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + denorm_min() noexcept { return char16_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char32_t + min() noexcept { return __glibcxx_min (char32_t); } + + static constexpr char32_t + max() noexcept { return __glibcxx_max (char32_t); } + + static constexpr char32_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char32_t); + static constexpr int digits10 = __glibcxx_digits10 (char32_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char32_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char32_t + epsilon() noexcept { return 0; } + + static constexpr char32_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char32_t + infinity() noexcept { return char32_t(); } + + static constexpr char32_t + quiet_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + signaling_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + denorm_min() noexcept { return char32_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; +#endif + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR short + min() _GLIBCXX_USE_NOEXCEPT { return -__SHRT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (short); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR short + infinity() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + denorm_min() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned short + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned short); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned short + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR int + min() _GLIBCXX_USE_NOEXCEPT { return -__INT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (int); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned int + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned int); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (long); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__ * 2ULL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#define __INT_N(TYPE, BITSIZE, EXT, UEXT) \ + __extension__ \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE - 1; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = (BITSIZE - 1) * 643L / 2136; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + EXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps \ + = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; \ + \ + __extension__ \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + max() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_max_b (unsigned TYPE, BITSIZE); } \ + \ + UEXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = BITSIZE * 643L / 2136; \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; + +#if __cplusplus >= 201103L + +#define __INT_N_201103(TYPE) \ + static constexpr TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#define __INT_N_U201103(TYPE) \ + static constexpr unsigned TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#else +#define __INT_N_201103(TYPE) +#define __INT_N_U201103(TYPE) +#endif + +#if !defined(__STRICT_ANSI__) +#ifdef __GLIBCXX_TYPE_INT_N_0 + __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), + __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), + __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), + __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), + __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3)) +#endif + +#elif defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + __INT_N(__int128, 128, + __INT_N_201103 (__int128), + __INT_N_U201103 (__int128)) +#endif + +#undef __INT_N +#undef __INT_N_201103 +#undef __INT_N_U201103 + + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR float + min() _GLIBCXX_USE_NOEXCEPT { return __FLT_MIN__; } + + static _GLIBCXX_CONSTEXPR float + max() _GLIBCXX_USE_NOEXCEPT { return __FLT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr float + lowest() noexcept { return -__FLT_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __FLT_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __FLT_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__FLT_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR float + epsilon() _GLIBCXX_USE_NOEXCEPT { return __FLT_EPSILON__; } + + static _GLIBCXX_CONSTEXPR float + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __FLT_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __FLT_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __FLT_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __FLT_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __FLT_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__FLT_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_float_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR float + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_valf(); } + + static _GLIBCXX_CONSTEXPR float + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanf(""); } + + static _GLIBCXX_CONSTEXPR float + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansf(""); } + + static _GLIBCXX_CONSTEXPR float + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __FLT_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_float_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_float_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_float_has_denorm_loss +#undef __glibcxx_float_traps +#undef __glibcxx_float_tinyness_before + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR double + min() _GLIBCXX_USE_NOEXCEPT { return __DBL_MIN__; } + + static _GLIBCXX_CONSTEXPR double + max() _GLIBCXX_USE_NOEXCEPT { return __DBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr double + lowest() noexcept { return -__DBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __DBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __DBL_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__DBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __DBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __DBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __DBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __DBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __DBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __DBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__DBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_val(); } + + static _GLIBCXX_CONSTEXPR double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nan(""); } + + static _GLIBCXX_CONSTEXPR double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nans(""); } + + static _GLIBCXX_CONSTEXPR double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __DBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_double_has_denorm_loss +#undef __glibcxx_double_traps +#undef __glibcxx_double_tinyness_before + +#if !(defined(__clang__) && !__STDC_HOSTED__) // clang in kernel context + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long double + min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MIN__; } + + static _GLIBCXX_CONSTEXPR long double + max() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long double + lowest() noexcept { return -__LDBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __LDBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __LDBL_DIG__; +#if __cplusplus >= 201103L + static _GLIBCXX_USE_CONSTEXPR int max_digits10 + = __glibcxx_max_digits10 (__LDBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR long double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __LDBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR long double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5L; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __LDBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __LDBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __LDBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __LDBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __LDBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__LDBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_long_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR long double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_vall(); } + + static _GLIBCXX_CONSTEXPR long double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanl(""); } + + static _GLIBCXX_CONSTEXPR long double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansl(""); } + + static _GLIBCXX_CONSTEXPR long double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_long_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = + __glibcxx_long_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_to_nearest; + }; + +#undef __glibcxx_long_double_has_denorm_loss +#undef __glibcxx_long_double_traps +#undef __glibcxx_long_double_tinyness_before + +#endif + +#define __glibcxx_concat3_(P,M,S) P ## M ## S +#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S) + +#if __cplusplus >= 201103L +# define __max_digits10 max_digits10 +#endif + +#define __glibcxx_float_n(BITSIZE) \ + __extension__ \ + template<> \ + struct numeric_limits<_Float##BITSIZE> \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + min() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_concat3 (__FLT, BITSIZE, _MIN__); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + max() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_concat3 (__FLT, BITSIZE, _MAX__); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + lowest() _GLIBCXX_USE_NOEXCEPT \ + { return -__glibcxx_concat3 (__FLT, BITSIZE, _MAX__); } \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = __glibcxx_concat3 (__FLT, BITSIZE, _MANT_DIG__); \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = __glibcxx_concat3 (__FLT, BITSIZE, _DIG__); \ + static _GLIBCXX_USE_CONSTEXPR int __max_digits10 \ + = __glibcxx_max_digits10 (__glibcxx_concat3 (__FLT, BITSIZE, \ + _MANT_DIG__)); \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; \ + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + epsilon() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_concat3 (__FLT, BITSIZE, _EPSILON__); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F##BITSIZE; } \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent \ + = __glibcxx_concat3 (__FLT, BITSIZE, _MIN_EXP__); \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 \ + = __glibcxx_concat3 (__FLT, BITSIZE, _MIN_10_EXP__); \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent \ + = __glibcxx_concat3 (__FLT, BITSIZE, _MAX_EXP__); \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 \ + = __glibcxx_concat3 (__FLT, BITSIZE, _MAX_10_EXP__); \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity \ + = __glibcxx_concat3 (__FLT, BITSIZE, _HAS_INFINITY__); \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN \ + = __glibcxx_concat3 (__FLT, BITSIZE, _HAS_QUIET_NAN__); \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN \ + = has_quiet_NaN; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = bool(__glibcxx_concat3 (__FLT, BITSIZE, _HAS_DENORM__)) \ + ? denorm_present : denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return __builtin_huge_valf##BITSIZE(); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return __builtin_nanf##BITSIZE(""); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return __builtin_nansf##BITSIZE(""); } \ + \ + static _GLIBCXX_CONSTEXPR _Float##BITSIZE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_concat3 (__FLT, BITSIZE, _DENORM_MIN__); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 \ + = has_infinity && has_quiet_NaN && has_denorm == denorm_present;\ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps = false; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_to_nearest; \ + }; \ + +#ifdef __STDCPP_FLOAT16_T__ +__glibcxx_float_n(16) +#endif +#ifdef __FLT32_DIG__ +__glibcxx_float_n(32) +#endif +#ifdef __FLT64_DIG__ +__glibcxx_float_n(64) +#endif +#ifdef __FLT128_DIG__ +__glibcxx_float_n(128) +#endif +#undef __glibcxx_float_n +#undef __glibcxx_concat3 +#undef __glibcxx_concat3_ + +#if __cplusplus >= 201103L +# undef __max_digits10 +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + __extension__ + template<> + struct numeric_limits<__gnu_cxx::__bfloat16_t> + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + min() _GLIBCXX_USE_NOEXCEPT + { return __BFLT16_MIN__; } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + max() _GLIBCXX_USE_NOEXCEPT + { return __BFLT16_MAX__; } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + lowest() _GLIBCXX_USE_NOEXCEPT + { return -__BFLT16_MAX__; } + + static _GLIBCXX_USE_CONSTEXPR int digits = __BFLT16_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __BFLT16_DIG__; +#if __cplusplus >= 201103L + static _GLIBCXX_USE_CONSTEXPR int max_digits10 + = __glibcxx_max_digits10 (__BFLT16_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + epsilon() _GLIBCXX_USE_NOEXCEPT + { return __BFLT16_EPSILON__; } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5BF16; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __BFLT16_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __BFLT16_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __BFLT16_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __BFLT16_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity + = __BFLT16_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN + = __BFLT16_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__BFLT16_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + infinity() _GLIBCXX_USE_NOEXCEPT + { return __gnu_cxx::__bfloat16_t(__builtin_huge_valf()); } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return __gnu_cxx::__bfloat16_t(__builtin_nanf("")); } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return __builtin_nansf16b(""); } + + static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return __BFLT16_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = false; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; +#endif // __STDCPP_BFLOAT16_T__ + +#if defined(_GLIBCXX_USE_FLOAT128) +// We either need Q literal suffixes, or IEEE double. +#if ! defined(__STRICT_ANSI__) || defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __extension__ + template<> + struct numeric_limits<__float128> + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR __float128 + min() _GLIBCXX_USE_NOEXCEPT + { +#ifdef __STRICT_ANSI__ + // 0x1.0p-30 * 0x1.0p-16352 + return double(9.3132257461547852e-10) * _S_1pm16352(); +#else + return __extension__ 0x1.0p-16382Q; +#endif + } + + static _GLIBCXX_CONSTEXPR __float128 + max() _GLIBCXX_USE_NOEXCEPT + { +#ifdef __STRICT_ANSI__ + // (0x1.fffffffffffffp+127 + 0x0.fffffffffffffp+75 + 0x0.ffp+23) + // * 0x1.0p16256 + return (__float128(double(3.4028236692093843e+38)) + + double(3.7778931862957153e+22) + double(8.35584e+6)) + * _S_1p16256(); +#else + return __extension__ 0x1.ffffffffffffffffffffffffffffp+16383Q; +#endif + } + + static _GLIBCXX_CONSTEXPR __float128 + lowest() _GLIBCXX_USE_NOEXCEPT + { return -max(); } + + static _GLIBCXX_USE_CONSTEXPR int digits = 113; + static _GLIBCXX_USE_CONSTEXPR int digits10 = 33; +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 35; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR __float128 + epsilon() _GLIBCXX_USE_NOEXCEPT + { return double(1.9259299443872359e-34); } + + static _GLIBCXX_CONSTEXPR __float128 + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = -16381; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = -4931; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 16384; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 4932; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = 1; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = 1; +#if __has_builtin(__builtin_nansq) \ + || (__has_builtin(__builtin_bit_cast) && __has_builtin(__builtin_nansf128)) + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true; +#else + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; +#endif + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR __float128 + infinity() _GLIBCXX_USE_NOEXCEPT + { return __builtin_huge_val(); } + + static _GLIBCXX_CONSTEXPR __float128 + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return __builtin_nan(""); } + + static _GLIBCXX_CONSTEXPR __float128 + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { +#if __has_builtin(__builtin_nansq) + return __builtin_nansq(""); +#elif __has_builtin(__builtin_bit_cast) && __has_builtin(__builtin_nansf128) + return __builtin_bit_cast(__float128, __builtin_nansf128("")); +#else + return quiet_NaN(); +#endif + } + + static _GLIBCXX_CONSTEXPR __float128 + denorm_min() _GLIBCXX_USE_NOEXCEPT + { +#if defined(__STRICT_ANSI__) || defined(__INTEL_COMPILER) + // 0x1.0p-142 * 0x1.0p-16352 + return double(1.7936620343357659e-43) * _S_1pm16352(); +#else + return __extension__ 0x1.0p-16494Q; +#endif + } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = has_signaling_NaN; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = false; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + +#if defined(__STRICT_ANSI__) || defined(__INTEL_COMPILER) + private: + static _GLIBCXX_CONSTEXPR __float128 + _S_4p(__float128 __v) _GLIBCXX_USE_NOEXCEPT + { return __v * __v * __v * __v; } + + static _GLIBCXX_CONSTEXPR __float128 + _S_1pm4088() _GLIBCXX_USE_NOEXCEPT + { return _S_4p(/* 0x1.0p-1022 */ double(2.2250738585072014e-308)); } + + static _GLIBCXX_CONSTEXPR __float128 + _S_1pm16352() _GLIBCXX_USE_NOEXCEPT + { return _S_4p(_S_1pm4088()); } + + static _GLIBCXX_CONSTEXPR __float128 + _S_1p4064() _GLIBCXX_USE_NOEXCEPT + { return _S_4p(/* 0x1.0p+1016 */ double(7.0222388080559215e+305)); } + + static _GLIBCXX_CONSTEXPR __float128 + _S_1p16256() _GLIBCXX_USE_NOEXCEPT + { return _S_4p(_S_1p4064()); } +#endif + }; +#endif // !__STRICT_ANSI__ || DOUBLE_IS_IEEE_BINARY64 +#endif // _GLIBCXX_USE_FLOAT128 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#undef __glibcxx_signed +#undef __glibcxx_min +#undef __glibcxx_max +#undef __glibcxx_digits +#undef __glibcxx_digits10 +#undef __glibcxx_max_digits10 + +#endif // _GLIBCXX_NUMERIC_LIMITS diff --git a/template/sysroot/include/limits.h b/template/sysroot/include/limits.h new file mode 100644 index 0000000..77f6383 --- /dev/null +++ b/template/sysroot/include/limits.h @@ -0,0 +1,184 @@ +/* Copyright (C) 1991-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _LIMITS_H___ +#define _LIMITS_H___ + +/* Number of bits in a `char'. */ +#undef CHAR_BIT +#define CHAR_BIT __CHAR_BIT__ + +/* Maximum length of a multibyte character. */ +#ifndef MB_LEN_MAX +#define MB_LEN_MAX 1 +#endif + +/* Minimum and maximum values a `signed char' can hold. */ +#undef SCHAR_MIN +#define SCHAR_MIN (-SCHAR_MAX - 1) +#undef SCHAR_MAX +#define SCHAR_MAX __SCHAR_MAX__ + +/* Maximum value an `unsigned char' can hold. (Minimum is 0). */ +#undef UCHAR_MAX +#if __SCHAR_MAX__ == __INT_MAX__ +# define UCHAR_MAX (SCHAR_MAX * 2U + 1U) +#else +# define UCHAR_MAX (SCHAR_MAX * 2 + 1) +#endif + +/* Minimum and maximum values a `char' can hold. */ +#ifdef __CHAR_UNSIGNED__ +# undef CHAR_MIN +# if __SCHAR_MAX__ == __INT_MAX__ +# define CHAR_MIN 0U +# else +# define CHAR_MIN 0 +# endif +# undef CHAR_MAX +# define CHAR_MAX UCHAR_MAX +#else +# undef CHAR_MIN +# define CHAR_MIN SCHAR_MIN +# undef CHAR_MAX +# define CHAR_MAX SCHAR_MAX +#endif + +/* Minimum and maximum values a `signed short int' can hold. */ +#undef SHRT_MIN +#define SHRT_MIN (-SHRT_MAX - 1) +#undef SHRT_MAX +#define SHRT_MAX __SHRT_MAX__ + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ +#undef USHRT_MAX +#if __SHRT_MAX__ == __INT_MAX__ +# define USHRT_MAX (SHRT_MAX * 2U + 1U) +#else +# define USHRT_MAX (SHRT_MAX * 2 + 1) +#endif + +/* Minimum and maximum values a `signed int' can hold. */ +#undef INT_MIN +#define INT_MIN (-INT_MAX - 1) +#undef INT_MAX +#define INT_MAX __INT_MAX__ + +/* Maximum value an `unsigned int' can hold. (Minimum is 0). */ +#undef UINT_MAX +#define UINT_MAX (INT_MAX * 2U + 1U) + +/* Minimum and maximum values a `signed long int' can hold. + (Same as `int'). */ +#undef LONG_MIN +#define LONG_MIN (-LONG_MAX - 1L) +#undef LONG_MAX +#define LONG_MAX __LONG_MAX__ + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +#undef ULONG_MAX +#define ULONG_MAX (LONG_MAX * 2UL + 1UL) + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# undef LLONG_MAX +# define LLONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULLONG_MAX +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +#endif + +#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__) +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LONG_LONG_MIN +# define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL) +# undef LONG_LONG_MAX +# define LONG_LONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULONG_LONG_MAX +# define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL) +#endif + +#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \ + || (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L)) +/* TS 18661-1 / C23 widths of integer types. */ +#if defined (__clang__) +# undef CHAR_WIDTH +# define CHAR_WIDTH CHAR_BIT +# undef SCHAR_WIDTH +# define SCHAR_WIDTH CHAR_BIT +# undef UCHAR_WIDTH +# define UCHAR_WIDTH CHAR_BIT +#else +# undef CHAR_WIDTH +# define CHAR_WIDTH __SCHAR_WIDTH__ +# undef SCHAR_WIDTH +# define SCHAR_WIDTH __SCHAR_WIDTH__ +# undef UCHAR_WIDTH +# define UCHAR_WIDTH __SCHAR_WIDTH__ +#endif +# undef SHRT_WIDTH +# define SHRT_WIDTH __SHRT_WIDTH__ +# undef USHRT_WIDTH +# define USHRT_WIDTH __SHRT_WIDTH__ +# undef INT_WIDTH +# define INT_WIDTH __INT_WIDTH__ +# undef UINT_WIDTH +# define UINT_WIDTH __INT_WIDTH__ +# undef LONG_WIDTH +# define LONG_WIDTH __LONG_WIDTH__ +# undef ULONG_WIDTH +# define ULONG_WIDTH __LONG_WIDTH__ +#if defined(__clang__) +# undef LLONG_WIDTH +# define LLONG_WIDTH __LLONG_WIDTH__ +# undef ULLONG_WIDTH +# define ULLONG_WIDTH __LLONG_WIDTH__ +#else +# undef LLONG_WIDTH +# define LLONG_WIDTH __LONG_LONG_WIDTH__ +# undef ULLONG_WIDTH +# define ULLONG_WIDTH __LONG_LONG_WIDTH__ +#endif +#endif + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L +/* C23 width and limit of _Bool. */ +# undef BOOL_MAX +# define BOOL_MAX 1 +# undef BOOL_WIDTH +# define BOOL_WIDTH 1 + +# ifdef __BITINT_MAXWIDTH__ +# undef BITINT_MAXWIDTH +# define BITINT_MAXWIDTH __BITINT_MAXWIDTH__ +# endif + +# define __STDC_VERSION_LIMITS_H__ 202311L +#endif + +#endif /* _LIMITS_H___ */ diff --git a/template/sysroot/include/lwpintrin.h b/template/sysroot/include/lwpintrin.h new file mode 100644 index 0000000..191154b --- /dev/null +++ b/template/sysroot/include/lwpintrin.h @@ -0,0 +1,107 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _LWPINTRIN_H_INCLUDED +#define _LWPINTRIN_H_INCLUDED + +#ifndef __LWP__ +#pragma GCC push_options +#pragma GCC target("lwp") +#define __DISABLE_LWP__ +#endif /* __LWP__ */ + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__llwpcb (void *__pcbAddress) +{ + __builtin_ia32_llwpcb (__pcbAddress); +} + +extern __inline void * __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__slwpcb (void) +{ + return __builtin_ia32_slwpcb (); +} + +#ifdef __OPTIMIZE__ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lwpval32 (unsigned int __data2, unsigned int __data1, unsigned int __flags) +{ + __builtin_ia32_lwpval32 (__data2, __data1, __flags); +} + +#ifdef __x86_64__ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lwpval64 (unsigned long long __data2, unsigned int __data1, + unsigned int __flags) +{ + __builtin_ia32_lwpval64 (__data2, __data1, __flags); +} +#endif +#else +#define __lwpval32(D2, D1, F) \ + (__builtin_ia32_lwpval32 ((unsigned int) (D2), (unsigned int) (D1), \ + (unsigned int) (F))) +#ifdef __x86_64__ +#define __lwpval64(D2, D1, F) \ + (__builtin_ia32_lwpval64 ((unsigned long long) (D2), (unsigned int) (D1), \ + (unsigned int) (F))) +#endif +#endif + + +#ifdef __OPTIMIZE__ +extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lwpins32 (unsigned int __data2, unsigned int __data1, unsigned int __flags) +{ + return __builtin_ia32_lwpins32 (__data2, __data1, __flags); +} + +#ifdef __x86_64__ +extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lwpins64 (unsigned long long __data2, unsigned int __data1, + unsigned int __flags) +{ + return __builtin_ia32_lwpins64 (__data2, __data1, __flags); +} +#endif +#else +#define __lwpins32(D2, D1, F) \ + (__builtin_ia32_lwpins32 ((unsigned int) (D2), (unsigned int) (D1), \ + (unsigned int) (F))) +#ifdef __x86_64__ +#define __lwpins64(D2, D1, F) \ + (__builtin_ia32_lwpins64 ((unsigned long long) (D2), (unsigned int) (D1), \ + (unsigned int) (F))) +#endif +#endif + +#ifdef __DISABLE_LWP__ +#undef __DISABLE_LWP__ +#pragma GCC pop_options +#endif /* __DISABLE_LWP__ */ + +#endif /* _LWPINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/lzcntintrin.h b/template/sysroot/include/lzcntintrin.h new file mode 100644 index 0000000..1a0712d --- /dev/null +++ b/template/sysroot/include/lzcntintrin.h @@ -0,0 +1,75 @@ +/* Copyright (C) 2009-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + + +#ifndef _LZCNTINTRIN_H_INCLUDED +#define _LZCNTINTRIN_H_INCLUDED + +#ifndef __LZCNT__ +#pragma GCC push_options +#pragma GCC target("lzcnt") +#define __DISABLE_LZCNT__ +#endif /* __LZCNT__ */ + +extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lzcnt16 (unsigned short __X) +{ + return __builtin_ia32_lzcnt_u16 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lzcnt32 (unsigned int __X) +{ + return __builtin_ia32_lzcnt_u32 (__X); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_lzcnt_u32 (unsigned int __X) +{ + return __builtin_ia32_lzcnt_u32 (__X); +} + +#ifdef __x86_64__ +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__lzcnt64 (unsigned long long __X) +{ + return __builtin_ia32_lzcnt_u64 (__X); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_lzcnt_u64 (unsigned long long __X) +{ + return __builtin_ia32_lzcnt_u64 (__X); +} +#endif + +#ifdef __DISABLE_LZCNT__ +#undef __DISABLE_LZCNT__ +#pragma GCC pop_options +#endif /* __DISABLE_LZCNT__ */ + +#endif /* _LZCNTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/memory b/template/sysroot/include/memory new file mode 100644 index 0000000..c984436 --- /dev/null +++ b/template/sysroot/include/memory @@ -0,0 +1,175 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/memory + * This is a Standard C++ Library header. + * @ingroup memory + */ + +#ifndef _GLIBCXX_MEMORY +#define _GLIBCXX_MEMORY 1 + +#pragma GCC system_header + +/** + * @defgroup memory Memory + * @ingroup utilities + * + * Components for memory allocation, deallocation, and management. + */ + +/** + * @defgroup pointer_abstractions Pointer Abstractions + * @ingroup memory + * + * Smart pointers, etc. + */ + +#include +#if _GLIBCXX_HOSTED +# include +# include +#endif +#include +#include +#include + +#if __cplusplus >= 201103L +# include +# include +# include +# include +# include +# include +# if _GLIBCXX_HOSTED +# include +# include +# endif +#endif + +#if __cplusplus < 201103L || _GLIBCXX_USE_DEPRECATED +# include +#endif + +#if __cplusplus > 201703L +# include +# include +#endif + +#if __cplusplus > 202002L +# include +#endif + +#define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_assume_aligned +#define __glibcxx_want_atomic_shared_ptr +#define __glibcxx_want_atomic_value_initialization +#define __glibcxx_want_constexpr_dynamic_alloc +#define __glibcxx_want_constexpr_memory +#define __glibcxx_want_enable_shared_from_this +#define __glibcxx_want_make_unique +#define __glibcxx_want_out_ptr +#define __glibcxx_want_parallel_algorithm +#define __glibcxx_want_ranges +#define __glibcxx_want_raw_memory_algorithms +#define __glibcxx_want_shared_ptr_arrays +#define __glibcxx_want_shared_ptr_weak_type +#define __glibcxx_want_smart_ptr_for_overwrite +#define __glibcxx_want_to_address +#define __glibcxx_want_transparent_operators +#include + +#if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @defgroup ptr_safety Pointer Safety and Garbage Collection + * @ingroup memory + * + * Utilities to assist with garbage collection in an implementation + * that supports strict pointer safety. + * This implementation only supports relaxed pointer safety + * and so these functions have no effect. + * + * C++11 20.6.4 [util.dynamic.safety], Pointer safety + * + * @{ + */ + +/// Constants representing the different types of pointer safety. +enum class pointer_safety { relaxed, preferred, strict }; + +/// Inform a garbage collector that an object is still in use. +inline void +declare_reachable(void*) { } + +/// Unregister an object previously registered with declare_reachable. +template + inline _Tp* + undeclare_reachable(_Tp* __p) { return __p; } + +/// Inform a garbage collector that a region of memory need not be traced. +inline void +declare_no_pointers(char*, size_t) { } + +/// Unregister a range previously registered with declare_no_pointers. +inline void +undeclare_no_pointers(char*, size_t) { } + +/// The type of pointer safety supported by the implementation. +inline pointer_safety +get_pointer_safety() noexcept { return pointer_safety::relaxed; } +/// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++11 to C++20 + +#ifdef __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED +// Parallel STL algorithms +# if _PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +# include +# else +// Otherwise just pull in forward declarations +# include +# endif +#endif // __cpp_lib_parallel_algorithm + +#endif /* _GLIBCXX_MEMORY */ diff --git a/template/sysroot/include/mm3dnow.h b/template/sysroot/include/mm3dnow.h new file mode 100644 index 0000000..68979e0 --- /dev/null +++ b/template/sysroot/include/mm3dnow.h @@ -0,0 +1,233 @@ +/* Copyright (C) 2004-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the mm3dnow.h (of supposedly AMD origin) included with + MSVC 7.1. */ + +#ifndef _MM3DNOW_H_INCLUDED +#define _MM3DNOW_H_INCLUDED + +#include +#include + +#if defined __x86_64__ && !defined __SSE__ || !defined __3dNOW__ +#pragma GCC push_options +#ifdef __x86_64__ +#pragma GCC target("sse,3dnow") +#else +#pragma GCC target("3dnow") +#endif +#define __DISABLE_3dNOW__ +#endif /* __3dNOW__ */ + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_femms (void) +{ + __builtin_ia32_femms(); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pavgusb (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pavgusb ((__v8qi)__A, (__v8qi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pf2id (__m64 __A) +{ + return (__m64)__builtin_ia32_pf2id ((__v2sf)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfacc (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfacc ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfadd (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfadd ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfcmpeq (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfcmpeq ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfcmpge (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfcmpge ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfcmpgt (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfcmpgt ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfmax (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfmax ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfmin (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfmin ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfmul (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfmul ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfrcp (__m64 __A) +{ + return (__m64)__builtin_ia32_pfrcp ((__v2sf)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfrcpit1 (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfrcpit1 ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfrcpit2 (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfrcpit2 ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfrsqrt (__m64 __A) +{ + return (__m64)__builtin_ia32_pfrsqrt ((__v2sf)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfrsqit1 (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfrsqit1 ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfsub (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfsub ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfsubr (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfsubr ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pi2fd (__m64 __A) +{ + return (__m64)__builtin_ia32_pi2fd ((__v2si)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmulhrw (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pmulhrw ((__v4hi)__A, (__v4hi)__B); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_prefetch (void *__P) +{ + __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_from_float (float __A) +{ + return __extension__ (__m64)(__v2sf){ __A, 0.0f }; +} + +extern __inline float __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_to_float (__m64 __A) +{ + union { __v2sf v; float a[2]; } __tmp; + __tmp.v = (__v2sf)__A; + return __tmp.a[0]; +} + +#ifdef __DISABLE_3dNOW__ +#undef __DISABLE_3dNOW__ +#pragma GCC pop_options +#endif /* __DISABLE_3dNOW__ */ + +#if defined __x86_64__ && !defined __SSE__ || !defined __3dNOW_A__ +#pragma GCC push_options +#ifdef __x86_64__ +#pragma GCC target("sse,3dnowa") +#else +#pragma GCC target("3dnowa") +#endif +#define __DISABLE_3dNOW_A__ +#endif /* __3dNOW_A__ */ + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pf2iw (__m64 __A) +{ + return (__m64)__builtin_ia32_pf2iw ((__v2sf)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfnacc (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfnacc ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pfpnacc (__m64 __A, __m64 __B) +{ + return (__m64)__builtin_ia32_pfpnacc ((__v2sf)__A, (__v2sf)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pi2fw (__m64 __A) +{ + return (__m64)__builtin_ia32_pi2fw ((__v2si)__A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pswapd (__m64 __A) +{ + return (__m64)__builtin_ia32_pswapdsf ((__v2sf)__A); +} + +#ifdef __DISABLE_3dNOW_A__ +#undef __DISABLE_3dNOW_A__ +#pragma GCC pop_options +#endif /* __DISABLE_3dNOW_A__ */ + +#endif /* _MM3DNOW_H_INCLUDED */ diff --git a/template/sysroot/include/mm_malloc.h b/template/sysroot/include/mm_malloc.h new file mode 100644 index 0000000..7e2ff62 --- /dev/null +++ b/template/sysroot/include/mm_malloc.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2004-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _MM_MALLOC_H_INCLUDED +#define _MM_MALLOC_H_INCLUDED + +#include +#if __STDC_HOSTED__ +#include +#endif + +static __inline__ void * +_mm_malloc (size_t __size, size_t __align) +{ + void * __malloc_ptr; + void * __aligned_ptr; + + /* Error if align is not a power of two. */ + if (__align & (__align - 1)) + { +#if __STDC_HOSTED__ + errno = EINVAL; +#endif + return ((void *) 0); + } + + if (__size == 0) + return ((void *) 0); + + /* Assume malloc'd pointer is aligned at least to sizeof (void*). + If necessary, add another sizeof (void*) to store the value + returned by malloc. Effectively this enforces a minimum alignment + of sizeof double. */ + if (__align < 2 * sizeof (void *)) + __align = 2 * sizeof (void *); + + __malloc_ptr = malloc (__size + __align); + if (!__malloc_ptr) + return ((void *) 0); + + /* Align We have at least sizeof (void *) space below malloc'd ptr. */ + __aligned_ptr = (void *) (((size_t) __malloc_ptr + __align) + & ~((size_t) (__align) - 1)); + + /* Store the original pointer just before p. */ + ((void **) __aligned_ptr)[-1] = __malloc_ptr; + + return __aligned_ptr; +} + +static __inline__ void +_mm_free (void *__aligned_ptr) +{ + if (__aligned_ptr) + free (((void **) __aligned_ptr)[-1]); +} + +#endif /* _MM_MALLOC_H_INCLUDED */ diff --git a/template/sysroot/include/mmintrin.h b/template/sysroot/include/mmintrin.h new file mode 100644 index 0000000..9b84bb6 --- /dev/null +++ b/template/sysroot/include/mmintrin.h @@ -0,0 +1,965 @@ +/* Copyright (C) 2002-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 9.0. */ + +#ifndef _MMINTRIN_H_INCLUDED +#define _MMINTRIN_H_INCLUDED + +#if defined __x86_64__ && !defined __SSE__ || !defined __MMX__ +#pragma GCC push_options +#ifdef __MMX_WITH_SSE__ +#pragma GCC target("sse2") +#elif defined __x86_64__ +#pragma GCC target("sse,mmx") +#else +#pragma GCC target("mmx") +#endif +#define __DISABLE_MMX__ +#endif /* __MMX__ */ + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__)); +typedef int __m32 __attribute__ ((__vector_size__ (4), __may_alias__)); +typedef short __m16 __attribute__ ((__vector_size__ (2), __may_alias__)); + +/* Unaligned version of the same type */ +typedef int __m64_u __attribute__ ((__vector_size__ (8), __may_alias__, __aligned__ (1))); +typedef int __m32_u __attribute__ ((__vector_size__ (4), \ + __may_alias__, __aligned__ (1))); +typedef short __m16_u __attribute__ ((__vector_size__ (2), \ + __may_alias__, __aligned__ (1))); + +/* Internal data types for implementing the intrinsics. */ +typedef int __v2si __attribute__ ((__vector_size__ (8))); +typedef short __v4hi __attribute__ ((__vector_size__ (8))); +typedef char __v8qi __attribute__ ((__vector_size__ (8))); +typedef long long __v1di __attribute__ ((__vector_size__ (8))); +typedef float __v2sf __attribute__ ((__vector_size__ (8))); + +/* Empty the multimedia state. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_empty (void) +{ + __builtin_ia32_emms (); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_empty (void) +{ + _mm_empty (); +} + +/* Convert I to a __m64 object. The integer is zero-extended to 64-bits. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi32_si64 (int __i) +{ + return (__m64) __builtin_ia32_vec_init_v2si (__i, 0); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_from_int (int __i) +{ + return _mm_cvtsi32_si64 (__i); +} + +#ifdef __x86_64__ +/* Convert I to a __m64 object. */ + +/* Intel intrinsic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_from_int64 (long long __i) +{ + return (__m64) __i; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_m64 (long long __i) +{ + return (__m64) __i; +} + +/* Microsoft intrinsic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64x_si64 (long long __i) +{ + return (__m64) __i; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pi64x (long long __i) +{ + return (__m64) __i; +} +#endif + +/* Convert the lower 32 bits of the __m64 object into an integer. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_si32 (__m64 __i) +{ + return __builtin_ia32_vec_ext_v2si ((__v2si)__i, 0); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_to_int (__m64 __i) +{ + return _mm_cvtsi64_si32 (__i); +} + +#ifdef __x86_64__ +/* Convert the __m64 object to a 64bit integer. */ + +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_to_int64 (__m64 __i) +{ + return (long long)__i; +} + +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtm64_si64 (__m64 __i) +{ + return (long long)__i; +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_si64x (__m64 __i) +{ + return (long long)__i; +} +#endif + +/* Pack the four 16-bit values from M1 into the lower four 8-bit values of + the result, and the four 16-bit values from M2 into the upper four 8-bit + values of the result, all with signed saturation. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_packsswb ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_packsswb (__m64 __m1, __m64 __m2) +{ + return _mm_packs_pi16 (__m1, __m2); +} + +/* Pack the two 32-bit values from M1 in to the lower two 16-bit values of + the result, and the two 32-bit values from M2 into the upper two 16-bit + values of the result, all with signed saturation. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_packssdw ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_packssdw (__m64 __m1, __m64 __m2) +{ + return _mm_packs_pi32 (__m1, __m2); +} + +/* Pack the four 16-bit values from M1 into the lower four 8-bit values of + the result, and the four 16-bit values from M2 into the upper four 8-bit + values of the result, all with unsigned saturation. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_pu16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_packuswb ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_packuswb (__m64 __m1, __m64 __m2) +{ + return _mm_packs_pu16 (__m1, __m2); +} + +/* Interleave the four 8-bit values from the high half of M1 with the four + 8-bit values from the high half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpckhbw ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpckhbw (__m64 __m1, __m64 __m2) +{ + return _mm_unpackhi_pi8 (__m1, __m2); +} + +/* Interleave the two 16-bit values from the high half of M1 with the two + 16-bit values from the high half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpckhwd ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpckhwd (__m64 __m1, __m64 __m2) +{ + return _mm_unpackhi_pi16 (__m1, __m2); +} + +/* Interleave the 32-bit value from the high half of M1 with the 32-bit + value from the high half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpckhdq ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpckhdq (__m64 __m1, __m64 __m2) +{ + return _mm_unpackhi_pi32 (__m1, __m2); +} + +/* Interleave the four 8-bit values from the low half of M1 with the four + 8-bit values from the low half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpcklbw ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpcklbw (__m64 __m1, __m64 __m2) +{ + return _mm_unpacklo_pi8 (__m1, __m2); +} + +/* Interleave the two 16-bit values from the low half of M1 with the two + 16-bit values from the low half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpcklwd ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpcklwd (__m64 __m1, __m64 __m2) +{ + return _mm_unpacklo_pi16 (__m1, __m2); +} + +/* Interleave the 32-bit value from the low half of M1 with the 32-bit + value from the low half of M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_punpckldq ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_punpckldq (__m64 __m1, __m64 __m2) +{ + return _mm_unpacklo_pi32 (__m1, __m2); +} + +/* Add the 8-bit values in M1 to the 8-bit values in M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddb (__m64 __m1, __m64 __m2) +{ + return _mm_add_pi8 (__m1, __m2); +} + +/* Add the 16-bit values in M1 to the 16-bit values in M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddw (__m64 __m1, __m64 __m2) +{ + return _mm_add_pi16 (__m1, __m2); +} + +/* Add the 32-bit values in M1 to the 32-bit values in M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddd ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddd (__m64 __m1, __m64 __m2) +{ + return _mm_add_pi32 (__m1, __m2); +} + +/* Add the 64-bit values in M1 to the 64-bit values in M2. */ +#ifndef __SSE2__ +#pragma GCC push_options +#ifdef __MMX_WITH_SSE__ +#pragma GCC target("sse2") +#else +#pragma GCC target("sse2,mmx") +#endif +#define __DISABLE_SSE2__ +#endif /* __SSE2__ */ + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_si64 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddq ((__v1di)__m1, (__v1di)__m2); +} +#ifdef __DISABLE_SSE2__ +#undef __DISABLE_SSE2__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE2__ */ + +/* Add the 8-bit values in M1 to the 8-bit values in M2 using signed + saturated arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddsb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddsb (__m64 __m1, __m64 __m2) +{ + return _mm_adds_pi8 (__m1, __m2); +} + +/* Add the 16-bit values in M1 to the 16-bit values in M2 using signed + saturated arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddsw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddsw (__m64 __m1, __m64 __m2) +{ + return _mm_adds_pi16 (__m1, __m2); +} + +/* Add the 8-bit values in M1 to the 8-bit values in M2 using unsigned + saturated arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pu8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddusb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddusb (__m64 __m1, __m64 __m2) +{ + return _mm_adds_pu8 (__m1, __m2); +} + +/* Add the 16-bit values in M1 to the 16-bit values in M2 using unsigned + saturated arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pu16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_paddusw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_paddusw (__m64 __m1, __m64 __m2) +{ + return _mm_adds_pu16 (__m1, __m2); +} + +/* Subtract the 8-bit values in M2 from the 8-bit values in M1. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubb (__m64 __m1, __m64 __m2) +{ + return _mm_sub_pi8 (__m1, __m2); +} + +/* Subtract the 16-bit values in M2 from the 16-bit values in M1. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubw (__m64 __m1, __m64 __m2) +{ + return _mm_sub_pi16 (__m1, __m2); +} + +/* Subtract the 32-bit values in M2 from the 32-bit values in M1. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubd ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubd (__m64 __m1, __m64 __m2) +{ + return _mm_sub_pi32 (__m1, __m2); +} + +/* Add the 64-bit values in M1 to the 64-bit values in M2. */ +#ifndef __SSE2__ +#pragma GCC push_options +#ifdef __MMX_WITH_SSE__ +#pragma GCC target("sse2") +#else +#pragma GCC target("sse2,mmx") +#endif +#define __DISABLE_SSE2__ +#endif /* __SSE2__ */ + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_si64 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubq ((__v1di)__m1, (__v1di)__m2); +} +#ifdef __DISABLE_SSE2__ +#undef __DISABLE_SSE2__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE2__ */ + +/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using signed + saturating arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubsb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubsb (__m64 __m1, __m64 __m2) +{ + return _mm_subs_pi8 (__m1, __m2); +} + +/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using + signed saturating arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubsw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubsw (__m64 __m1, __m64 __m2) +{ + return _mm_subs_pi16 (__m1, __m2); +} + +/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using + unsigned saturating arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_pu8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubusb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubusb (__m64 __m1, __m64 __m2) +{ + return _mm_subs_pu8 (__m1, __m2); +} + +/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using + unsigned saturating arithmetic. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_subs_pu16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_psubusw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psubusw (__m64 __m1, __m64 __m2) +{ + return _mm_subs_pu16 (__m1, __m2); +} + +/* Multiply four 16-bit values in M1 by four 16-bit values in M2 producing + four 32-bit intermediate results, which are then summed by pairs to + produce two 32-bit results. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_madd_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pmaddwd ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmaddwd (__m64 __m1, __m64 __m2) +{ + return _mm_madd_pi16 (__m1, __m2); +} + +/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in + M2 and produce the high 16 bits of the 32-bit results. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhi_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pmulhw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmulhw (__m64 __m1, __m64 __m2) +{ + return _mm_mulhi_pi16 (__m1, __m2); +} + +/* Multiply four 16-bit values in M1 by four 16-bit values in M2 and produce + the low 16 bits of the results. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mullo_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pmullw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmullw (__m64 __m1, __m64 __m2) +{ + return _mm_mullo_pi16 (__m1, __m2); +} + +/* Shift four 16-bit values in M left by COUNT. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_pi16 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psllw ((__v4hi)__m, (__v4hi)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psllw (__m64 __m, __m64 __count) +{ + return _mm_sll_pi16 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_pi16 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psllwi ((__v4hi)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psllwi (__m64 __m, int __count) +{ + return _mm_slli_pi16 (__m, __count); +} + +/* Shift two 32-bit values in M left by COUNT. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_pi32 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_pslld ((__v2si)__m, (__v2si)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pslld (__m64 __m, __m64 __count) +{ + return _mm_sll_pi32 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_pi32 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_pslldi ((__v2si)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pslldi (__m64 __m, int __count) +{ + return _mm_slli_pi32 (__m, __count); +} + +/* Shift the 64-bit value in M left by COUNT. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sll_si64 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psllq ((__v1di)__m, (__v1di)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psllq (__m64 __m, __m64 __count) +{ + return _mm_sll_si64 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_si64 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psllqi ((__v1di)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psllqi (__m64 __m, int __count) +{ + return _mm_slli_si64 (__m, __count); +} + +/* Shift four 16-bit values in M right by COUNT; shift in the sign bit. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sra_pi16 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psraw ((__v4hi)__m, (__v4hi)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psraw (__m64 __m, __m64 __count) +{ + return _mm_sra_pi16 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srai_pi16 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psrawi ((__v4hi)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrawi (__m64 __m, int __count) +{ + return _mm_srai_pi16 (__m, __count); +} + +/* Shift two 32-bit values in M right by COUNT; shift in the sign bit. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sra_pi32 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psrad ((__v2si)__m, (__v2si)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrad (__m64 __m, __m64 __count) +{ + return _mm_sra_pi32 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srai_pi32 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psradi ((__v2si)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psradi (__m64 __m, int __count) +{ + return _mm_srai_pi32 (__m, __count); +} + +/* Shift four 16-bit values in M right by COUNT; shift in zeros. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_pi16 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psrlw ((__v4hi)__m, (__v4hi)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrlw (__m64 __m, __m64 __count) +{ + return _mm_srl_pi16 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_pi16 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psrlwi ((__v4hi)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrlwi (__m64 __m, int __count) +{ + return _mm_srli_pi16 (__m, __count); +} + +/* Shift two 32-bit values in M right by COUNT; shift in zeros. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_pi32 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psrld ((__v2si)__m, (__v2si)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrld (__m64 __m, __m64 __count) +{ + return _mm_srl_pi32 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_pi32 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psrldi ((__v2si)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrldi (__m64 __m, int __count) +{ + return _mm_srli_pi32 (__m, __count); +} + +/* Shift the 64-bit value in M left by COUNT; shift in zeros. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srl_si64 (__m64 __m, __m64 __count) +{ + return (__m64) __builtin_ia32_psrlq ((__v1di)__m, (__v1di)__count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrlq (__m64 __m, __m64 __count) +{ + return _mm_srl_si64 (__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_si64 (__m64 __m, int __count) +{ + return (__m64) __builtin_ia32_psrlqi ((__v1di)__m, __count); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psrlqi (__m64 __m, int __count) +{ + return _mm_srli_si64 (__m, __count); +} + +/* Bit-wise AND the 64-bit values in M1 and M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_and_si64 (__m64 __m1, __m64 __m2) +{ + return __builtin_ia32_pand (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pand (__m64 __m1, __m64 __m2) +{ + return _mm_and_si64 (__m1, __m2); +} + +/* Bit-wise complement the 64-bit value in M1 and bit-wise AND it with the + 64-bit value in M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_andnot_si64 (__m64 __m1, __m64 __m2) +{ + return __builtin_ia32_pandn (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pandn (__m64 __m1, __m64 __m2) +{ + return _mm_andnot_si64 (__m1, __m2); +} + +/* Bit-wise inclusive OR the 64-bit values in M1 and M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_si64 (__m64 __m1, __m64 __m2) +{ + return __builtin_ia32_por (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_por (__m64 __m1, __m64 __m2) +{ + return _mm_or_si64 (__m1, __m2); +} + +/* Bit-wise exclusive OR the 64-bit values in M1 and M2. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_si64 (__m64 __m1, __m64 __m2) +{ + return __builtin_ia32_pxor (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pxor (__m64 __m1, __m64 __m2) +{ + return _mm_xor_si64 (__m1, __m2); +} + +/* Compare eight 8-bit values. The result of the comparison is 0xFF if the + test is true and zero if false. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpeqb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpeqb (__m64 __m1, __m64 __m2) +{ + return _mm_cmpeq_pi8 (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_pi8 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpgtb ((__v8qi)__m1, (__v8qi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpgtb (__m64 __m1, __m64 __m2) +{ + return _mm_cmpgt_pi8 (__m1, __m2); +} + +/* Compare four 16-bit values. The result of the comparison is 0xFFFF if + the test is true and zero if false. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpeqw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpeqw (__m64 __m1, __m64 __m2) +{ + return _mm_cmpeq_pi16 (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_pi16 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpgtw ((__v4hi)__m1, (__v4hi)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpgtw (__m64 __m1, __m64 __m2) +{ + return _mm_cmpgt_pi16 (__m1, __m2); +} + +/* Compare two 32-bit values. The result of the comparison is 0xFFFFFFFF if + the test is true and zero if false. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpeqd ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpeqd (__m64 __m1, __m64 __m2) +{ + return _mm_cmpeq_pi32 (__m1, __m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_pi32 (__m64 __m1, __m64 __m2) +{ + return (__m64) __builtin_ia32_pcmpgtd ((__v2si)__m1, (__v2si)__m2); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pcmpgtd (__m64 __m1, __m64 __m2) +{ + return _mm_cmpgt_pi32 (__m1, __m2); +} + +/* Creates a 64-bit zero. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_si64 (void) +{ + return (__m64)0LL; +} + +/* Creates a vector of two 32-bit values; I0 is least significant. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pi32 (int __i1, int __i0) +{ + return (__m64) __builtin_ia32_vec_init_v2si (__i0, __i1); +} + +/* Creates a vector of four 16-bit values; W0 is least significant. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pi16 (short __w3, short __w2, short __w1, short __w0) +{ + return (__m64) __builtin_ia32_vec_init_v4hi (__w0, __w1, __w2, __w3); +} + +/* Creates a vector of eight 8-bit values; B0 is least significant. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_pi8 (char __b7, char __b6, char __b5, char __b4, + char __b3, char __b2, char __b1, char __b0) +{ + return (__m64) __builtin_ia32_vec_init_v8qi (__b0, __b1, __b2, __b3, + __b4, __b5, __b6, __b7); +} + +/* Similar, but with the arguments in reverse order. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_pi32 (int __i0, int __i1) +{ + return _mm_set_pi32 (__i1, __i0); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_pi16 (short __w0, short __w1, short __w2, short __w3) +{ + return _mm_set_pi16 (__w3, __w2, __w1, __w0); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_pi8 (char __b0, char __b1, char __b2, char __b3, + char __b4, char __b5, char __b6, char __b7) +{ + return _mm_set_pi8 (__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0); +} + +/* Creates a vector of two 32-bit values, both elements containing I. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pi32 (int __i) +{ + return _mm_set_pi32 (__i, __i); +} + +/* Creates a vector of four 16-bit values, all elements containing W. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pi16 (short __w) +{ + return _mm_set_pi16 (__w, __w, __w, __w); +} + +/* Creates a vector of eight 8-bit values, all elements containing B. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pi8 (char __b) +{ + return _mm_set_pi8 (__b, __b, __b, __b, __b, __b, __b, __b); +} +#ifdef __DISABLE_MMX__ +#undef __DISABLE_MMX__ +#pragma GCC pop_options +#endif /* __DISABLE_MMX__ */ + +#endif /* _MMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/montauk/config.h b/template/sysroot/include/montauk/config.h new file mode 100644 index 0000000..eda5df4 --- /dev/null +++ b/template/sysroot/include/montauk/config.h @@ -0,0 +1,429 @@ +/* + * config.h + * Config file manager for MontaukOS programs + * Loads, modifies, and saves TOML config files from 0:/config/ + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include +#include + +namespace montauk { +namespace config { + + static constexpr const char* CONFIG_DIR = "0:/config"; + + // ---- Serializer (Doc -> TOML text) ---- + + namespace detail { + + struct Writer { + char* buf; + int len; + int cap; + + void init() { + cap = 1024; + buf = (char*)montauk::malloc(cap); + len = 0; + buf[0] = '\0'; + } + + void destroy() { + if (buf) montauk::mfree(buf); + buf = nullptr; + len = 0; + cap = 0; + } + + void grow(int need) { + if (len + need < cap) return; + int newCap = cap; + while (newCap <= len + need) newCap *= 2; + char* nb = (char*)montauk::malloc(newCap); + montauk::memcpy(nb, buf, len); + montauk::mfree(buf); + buf = nb; + cap = newCap; + } + + void put(char c) { + grow(2); + buf[len++] = c; + buf[len] = '\0'; + } + + void puts(const char* s) { + int n = montauk::slen(s); + grow(n + 1); + montauk::memcpy(buf + len, s, n); + len += n; + buf[len] = '\0'; + } + + void put_int(int64_t v) { + if (v < 0) { put('-'); v = -v; } + if (v == 0) { put('0'); return; } + char tmp[24]; + int n = 0; + while (v > 0) { tmp[n++] = '0' + (v % 10); v /= 10; } + for (int i = n - 1; i >= 0; i--) put(tmp[i]); + } + + // Write a TOML-escaped string value + void put_string(const char* s) { + put('"'); + while (*s) { + switch (*s) { + case '"': puts("\\\""); break; + case '\\': puts("\\\\"); break; + case '\n': puts("\\n"); break; + case '\t': puts("\\t"); break; + case '\r': puts("\\r"); break; + default: put(*s); break; + } + s++; + } + put('"'); + } + + void write_value(toml::Value* v) { + switch (v->type) { + case toml::Type::String: + put_string(v->str); + break; + case toml::Type::Int: + put_int(v->ival); + break; + case toml::Type::Bool: + puts(v->bval ? "true" : "false"); + break; + case toml::Type::Array: { + put('['); + for (int i = 0; i < v->array.count; i++) { + if (i > 0) puts(", "); + write_value(v->array.items[i]); + } + put(']'); + break; + } + case toml::Type::Table: + // Inline tables are not re-serialized here; + // their entries are flattened in the doc + break; + } + } + }; + + // Extract the table prefix from a dotted key (everything before last dot) + // Returns length of prefix, or 0 if no dot + inline int key_table(const char* key, char* out, int outSz) { + int lastDot = -1; + int n = montauk::slen(key); + for (int i = 0; i < n; i++) { + if (key[i] == '.') lastDot = i; + } + if (lastDot <= 0) { out[0] = '\0'; return 0; } + int cp = lastDot < outSz - 1 ? lastDot : outSz - 1; + montauk::memcpy(out, key, cp); + out[cp] = '\0'; + return cp; + } + + // Extract the bare key (after last dot) + inline const char* key_bare(const char* key) { + const char* last = key; + while (*key) { + if (*key == '.') last = key + 1; + key++; + } + return last; + } + + } // namespace detail + + // Serialize a Doc back to TOML text. Caller must montauk::mfree() the result. + inline char* serialize(toml::Doc* doc) { + detail::Writer w; + w.init(); + + char currentTable[256] = {}; + + for (int i = 0; i < doc->entries.count; i++) { + auto* v = doc->entries.items[i]; + if (!v->key) continue; + + // Skip Table entries that only serve as section markers — + // we emit [table] headers based on the keys of actual values + if (v->type == toml::Type::Table && v->array.count == 0) + continue; + + // Determine table prefix for this key + char table[256]; + detail::key_table(v->key, table, sizeof(table)); + + // Emit [table] header if the section changed + if (!montauk::streq(table, currentTable)) { + montauk::strcpy(currentTable, table); + if (table[0]) { + if (w.len > 0) w.put('\n'); + w.put('['); + w.puts(table); + w.puts("]\n"); + } + } + + // Emit key = value + w.puts(detail::key_bare(v->key)); + w.puts(" = "); + w.write_value(v); + w.put('\n'); + } + + return w.buf; + } + + // ---- File operations ---- + + // Ensure the config directory exists + inline void ensure_dir() { + montauk::fmkdir(CONFIG_DIR); + } + + // Build full path: "0:/config/.toml" + inline void build_path(char* out, int outSz, const char* name) { + int p = 0; + const char* dir = CONFIG_DIR; + while (*dir && p < outSz - 2) out[p++] = *dir++; + out[p++] = '/'; + while (*name && p < outSz - 6) out[p++] = *name++; + // Append ".toml" + const char* ext = ".toml"; + while (*ext && p < outSz - 1) out[p++] = *ext++; + out[p] = '\0'; + } + + // Load a config file by name (without extension). + // Returns an initialized Doc (empty if file doesn't exist). + inline toml::Doc load(const char* name) { + char path[128]; + build_path(path, sizeof(path), name); + + int handle = montauk::open(path); + if (handle < 0) { + toml::Doc doc; + doc.init(); + return doc; + } + + uint64_t size = montauk::getsize(handle); + if (size == 0) { + montauk::close(handle); + toml::Doc doc; + doc.init(); + return doc; + } + + char* text = (char*)montauk::malloc(size + 1); + montauk::read(handle, (uint8_t*)text, 0, size); + montauk::close(handle); + text[size] = '\0'; + + toml::Doc doc = toml::parse(text); + montauk::mfree(text); + return doc; + } + + // Save a Doc to disk as a TOML file. + // Creates the file if it doesn't exist. + // Returns 0 on success, negative on error. + inline int save(const char* name, toml::Doc* doc) { + ensure_dir(); + + char path[128]; + build_path(path, sizeof(path), name); + + char* text = serialize(doc); + int textLen = montauk::slen(text); + + // Delete and recreate to ensure file is exactly the right size + // (no ftruncate syscall available, so this avoids stale trailing data) + montauk::fdelete(path); + int handle = montauk::fcreate(path); + if (handle < 0) { + montauk::mfree(text); + return -1; + } + + int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen); + montauk::close(handle); + montauk::mfree(text); + return ret < 0 ? ret : 0; + } + + // ---- Per-user config ---- + + // Build path: "0:/users//config/.toml" + inline void build_user_path(char* out, int outSz, const char* username, const char* name) { + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < outSz - 2) out[p++] = *prefix++; + while (*username && p < outSz - 2) out[p++] = *username++; + const char* mid = "/config/"; + while (*mid && p < outSz - 2) out[p++] = *mid++; + while (*name && p < outSz - 6) out[p++] = *name++; + const char* ext = ".toml"; + while (*ext && p < outSz - 1) out[p++] = *ext++; + out[p] = '\0'; + } + + // Ensure per-user config directory exists + inline void ensure_user_dir(const char* username) { + char dir[128]; + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < 126) dir[p++] = *prefix++; + while (*username && p < 126) dir[p++] = *username++; + dir[p] = '\0'; + montauk::fmkdir(dir); + + const char* suffix = "/config"; + while (*suffix && p < 126) dir[p++] = *suffix++; + dir[p] = '\0'; + montauk::fmkdir(dir); + } + + // Load a per-user config file + inline toml::Doc load_user(const char* username, const char* name) { + char path[192]; + build_user_path(path, sizeof(path), username, name); + + int handle = montauk::open(path); + if (handle < 0) { + toml::Doc doc; + doc.init(); + return doc; + } + + uint64_t size = montauk::getsize(handle); + if (size == 0) { + montauk::close(handle); + toml::Doc doc; + doc.init(); + return doc; + } + + char* text = (char*)montauk::malloc(size + 1); + montauk::read(handle, (uint8_t*)text, 0, size); + montauk::close(handle); + text[size] = '\0'; + + toml::Doc doc = toml::parse(text); + montauk::mfree(text); + return doc; + } + + // Save a per-user config file + inline int save_user(const char* username, const char* name, toml::Doc* doc) { + ensure_user_dir(username); + + char path[192]; + build_user_path(path, sizeof(path), username, name); + + char* text = serialize(doc); + int textLen = montauk::slen(text); + + montauk::fdelete(path); + int handle = montauk::fcreate(path); + if (handle < 0) { + montauk::mfree(text); + return -1; + } + + int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen); + montauk::close(handle); + montauk::mfree(text); + return ret < 0 ? ret : 0; + } + + // Delete a config file. Returns 0 on success. + inline int remove(const char* name) { + char path[128]; + build_path(path, sizeof(path), name); + return montauk::fdelete(path); + } + + // ---- In-place modification helpers ---- + + // Free any dynamically allocated data owned by a value (without freeing key) + namespace detail { + inline void free_value_data(toml::Value* v) { + if (v->type == toml::Type::String && v->str) + montauk::mfree(v->str); + else if (v->type == toml::Type::Array || v->type == toml::Type::Table) { + for (int i = 0; i < v->array.count; i++) { + if (v->array.items[i]) v->array.items[i]->destroy(); + } + if (v->array.items) montauk::mfree(v->array.items); + v->array.items = nullptr; + v->array.count = 0; + v->array.cap = 0; + } + } + } + + // Set or overwrite a string value in the doc. + inline void set_string(toml::Doc* doc, const char* key, const char* val) { + auto* existing = doc->get(key); + if (existing) { + detail::free_value_data(existing); + existing->type = toml::Type::String; + existing->str = toml::Value::dup(val); + } else { + doc->entries.push(toml::Value::make_string(key, val, montauk::slen(val))); + } + } + + // Set or overwrite an integer value in the doc. + inline void set_int(toml::Doc* doc, const char* key, int64_t val) { + auto* existing = doc->get(key); + if (existing) { + detail::free_value_data(existing); + existing->type = toml::Type::Int; + existing->ival = val; + } else { + doc->entries.push(toml::Value::make_int(key, val)); + } + } + + // Set or overwrite a boolean value in the doc. + inline void set_bool(toml::Doc* doc, const char* key, bool val) { + auto* existing = doc->get(key); + if (existing) { + detail::free_value_data(existing); + existing->type = toml::Type::Bool; + existing->bval = val; + } else { + doc->entries.push(toml::Value::make_bool(key, val)); + } + } + + // Remove a key from the doc. + inline bool unset(toml::Doc* doc, const char* key) { + for (int i = 0; i < doc->entries.count; i++) { + auto* v = doc->entries.items[i]; + if (v->key && montauk::streq(v->key, key)) { + v->destroy(); + // Shift remaining entries down + for (int j = i; j < doc->entries.count - 1; j++) + doc->entries.items[j] = doc->entries.items[j + 1]; + doc->entries.count--; + return true; + } + } + return false; + } + +} // namespace config +} // namespace montauk diff --git a/template/sysroot/include/montauk/heap.h b/template/sysroot/include/montauk/heap.h new file mode 100644 index 0000000..283eeac --- /dev/null +++ b/template/sysroot/include/montauk/heap.h @@ -0,0 +1,246 @@ +/* + * heap.h + * Userspace heap allocator for MontaukOS programs + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include +#include + +namespace montauk { +namespace heap_detail { + + static constexpr uint64_t HEADER_MAGIC = 0x5A484541; // "ZHEA" + static constexpr uint64_t FREED_MAGIC = 0xDEADFEEE; + + struct Header { + uint64_t magic; + uint64_t size; // user-requested size + } __attribute__((packed)); + + struct FreeNode { + uint64_t size; // total size of this free block (including node) + FreeNode* next; + }; + + // Segregated free lists: power-of-2 size classes for blocks <= 4096 bytes. + // Blocks larger than 4096 go to the overflow list. + static constexpr int NUM_BUCKETS = 8; + static constexpr uint64_t BUCKET_SIZES[NUM_BUCKETS] = { + 32, 64, 128, 256, 512, 1024, 2048, 4096 + }; + + // Per-process heap state — must be `inline` (not `static`) so that all + // translation units in a multi-TU program share a single heap. + inline FreeNode* g_buckets[NUM_BUCKETS] = {}; + inline FreeNode g_overflow{0, nullptr}; + inline bool g_initialized = false; + + static inline Header* get_header(void* block) { + return (Header*)((uint8_t*)block - sizeof(Header)); + } + + // Determine which bucket a block size belongs to, or -1 for overflow + static inline int bucket_index(uint64_t blockSize) { + if (blockSize <= 32) return 0; + if (blockSize <= 64) return 1; + if (blockSize <= 128) return 2; + if (blockSize <= 256) return 3; + if (blockSize <= 512) return 4; + if (blockSize <= 1024) return 5; + if (blockSize <= 2048) return 6; + if (blockSize <= 4096) return 7; + return -1; + } + + // Insert into overflow list (sorted by address, with adjacent-block coalescing) + static inline void insert_overflow(void* ptr, uint64_t size) { + auto* node = (FreeNode*)ptr; + node->size = size; + + FreeNode* prev = &g_overflow; + FreeNode* cur = g_overflow.next; + while (cur != nullptr && cur < node) { + prev = cur; + cur = cur->next; + } + + bool merged_prev = false; + if (prev != &g_overflow && + (uint8_t*)prev + prev->size == (uint8_t*)node) { + prev->size += size; + node = prev; + merged_prev = true; + } + + if (cur != nullptr && + (uint8_t*)node + node->size == (uint8_t*)cur) { + node->size += cur->size; + node->next = cur->next; + if (!merged_prev) prev->next = node; + } else if (!merged_prev) { + node->next = cur; + prev->next = node; + } + } + + // Take a block of at least `needed` bytes from the overflow list. + // Splits remainder back into overflow if worthwhile. + static inline void* take_from_overflow(uint64_t needed) { + FreeNode* prev = &g_overflow; + FreeNode* cur = g_overflow.next; + + while (cur != nullptr) { + if (cur->size >= needed) { + uint64_t blockSize = cur->size; + prev->next = cur->next; + + if (blockSize > needed + sizeof(FreeNode) + 16) { + insert_overflow((uint8_t*)cur + needed, blockSize - needed); + } + return (void*)cur; + } + prev = cur; + cur = cur->next; + } + return nullptr; + } + + static inline bool grow(uint64_t bytes) { + uint64_t pages = (bytes + 0xFFF) / 0x1000; + if (pages < 4) pages = 4; + + void* mem = montauk::alloc(pages * 0x1000); + if (mem == nullptr) return false; + insert_overflow(mem, pages * 0x1000); + return true; + } + + // Refill a small-block bucket by carving a page-sized chunk from overflow + static inline bool refill_bucket(int idx) { + uint64_t bsize = BUCKET_SIZES[idx]; + uint64_t chunk = (bsize < 4096) ? 4096 : bsize; + + void* block = take_from_overflow(chunk); + if (block == nullptr) { + if (!grow(chunk)) return false; + block = take_from_overflow(chunk); + if (block == nullptr) return false; + } + + uint64_t count = chunk / bsize; + for (uint64_t i = 0; i < count; i++) { + auto* node = (FreeNode*)((uint8_t*)block + i * bsize); + node->size = bsize; + node->next = g_buckets[idx]; + g_buckets[idx] = node; + } + return true; + } + +} // namespace heap_detail + + // ---- Public API ---- + + inline void* malloc(uint64_t size) { + using namespace heap_detail; + + if (!g_initialized) { + grow(16 * 0x1000); // seed with 64 KiB + g_initialized = true; + } + + // Guard against overflow: size + Header must not wrap + if (size > UINT64_MAX - sizeof(Header) - 15) + return nullptr; + + uint64_t needed = size + sizeof(Header); + needed = (needed + 15) & ~15ULL; + + int idx = bucket_index(needed); + + if (idx >= 0) { + // Small allocation — use segregated bucket (O(1)) + if (g_buckets[idx] == nullptr && !refill_bucket(idx)) + return nullptr; + + FreeNode* node = g_buckets[idx]; + g_buckets[idx] = node->next; + + Header* header = (Header*)node; + header->magic = HEADER_MAGIC; + header->size = size; + return (void*)((uint8_t*)header + sizeof(Header)); + } + + // Large allocation — search overflow list + void* block = take_from_overflow(needed); + if (block == nullptr) { + if (!grow(needed)) return nullptr; + block = take_from_overflow(needed); + if (block == nullptr) return nullptr; + } + + Header* header = (Header*)block; + header->magic = HEADER_MAGIC; + header->size = size; + return (void*)((uint8_t*)header + sizeof(Header)); + } + + inline void mfree(void* ptr) { + using namespace heap_detail; + + if (ptr == nullptr) return; + + Header* header = get_header(ptr); + + if (header->magic == FREED_MAGIC) return; // double-free + if (header->magic != HEADER_MAGIC) return; // corrupt + header->magic = FREED_MAGIC; + + uint64_t blockSize = header->size + sizeof(Header); + blockSize = (blockSize + 15) & ~15ULL; + + int idx = bucket_index(blockSize); + + if (idx >= 0) { + // Small block — push onto bucket (O(1)) + auto* node = (FreeNode*)header; + node->size = BUCKET_SIZES[idx]; + node->next = g_buckets[idx]; + g_buckets[idx] = node; + } else { + // Large block — sorted insert with coalescing + insert_overflow((void*)header, blockSize); + } + } + + inline void* realloc(void* ptr, uint64_t size) { + if (ptr == nullptr) return malloc(size); + + auto* header = heap_detail::get_header(ptr); + uint64_t old = header->size; + + // Compute actual block size (accounting for bucket rounding) + uint64_t oldBlock = (old + sizeof(heap_detail::Header) + 15) & ~15ULL; + int idx = heap_detail::bucket_index(oldBlock); + if (idx >= 0) oldBlock = heap_detail::BUCKET_SIZES[idx]; + + uint64_t newNeed = (size + sizeof(heap_detail::Header) + 15) & ~15ULL; + if (newNeed <= oldBlock) { + header->size = size; + return ptr; + } + + void* newBlock = malloc(size); + if (newBlock == nullptr) return nullptr; + + uint64_t copySize = (old < size) ? old : size; + memcpy(newBlock, ptr, copySize); + + mfree(ptr); + return newBlock; + } + +} // namespace montauk diff --git a/template/sysroot/include/montauk/string.h b/template/sysroot/include/montauk/string.h new file mode 100644 index 0000000..821a506 --- /dev/null +++ b/template/sysroot/include/montauk/string.h @@ -0,0 +1,108 @@ +/* + * string.h + * Common string and memory utility functions for MontaukOS programs + * Copyright (c) 2025-2026 Daniel Hammer +*/ + +#pragma once +#include + +namespace montauk { + + inline int slen(const char* s) { + int n = 0; + while (s[n]) n++; + return n; + } + + inline bool streq(const char* a, const char* b) { + while (*a && *b) { + if (*a != *b) return false; + a++; b++; + } + return *a == *b; + } + + inline bool starts_with(const char* str, const char* prefix) { + while (*prefix) { + if (*str != *prefix) return false; + str++; prefix++; + } + return true; + } + + inline const char* skip_spaces(const char* s) { + while (*s == ' ') s++; + return s; + } + + inline void memcpy(void* dst, const void* src, uint64_t n) { + auto* d = (uint8_t*)dst; + auto* s = (const uint8_t*)src; + + // Byte copy until 8-byte aligned + while (n && ((uint64_t)d & 7)) { *d++ = *s++; n--; } + + // Bulk 8-byte copy + auto* d8 = (uint64_t*)d; + auto* s8 = (const uint64_t*)s; + uint64_t words = n / 8; + for (uint64_t i = 0; i < words; i++) d8[i] = s8[i]; + + // Remainder + d = (uint8_t*)(d8 + words); + s = (const uint8_t*)(s8 + words); + for (uint64_t i = 0; i < (n & 7); i++) d[i] = s[i]; + } + + inline void memmove(void* dst, const void* src, uint64_t n) { + auto* d = (uint8_t*)dst; + auto* s = (const uint8_t*)src; + if (d < s || d >= s + n) { + memcpy(dst, src, n); + } else { + // Backward copy — bulk 8 bytes at a time from end + d += n; s += n; + while (n && ((uint64_t)d & 7)) { *--d = *--s; n--; } + auto* d8 = (uint64_t*)d; + auto* s8 = (const uint64_t*)s; + uint64_t words = n / 8; + for (uint64_t i = 1; i <= words; i++) d8[-i] = s8[-i]; + d = (uint8_t*)(d8 - words); + s = (const uint8_t*)(s8 - words); + for (uint64_t i = 1; i <= (n & 7); i++) d[-i] = s[-i]; + } + } + + inline void memset(void* dst, int val, uint64_t n) { + auto* d = (uint8_t*)dst; + uint8_t v = (uint8_t)val; + + // Byte fill until 8-byte aligned + while (n && ((uint64_t)d & 7)) { *d++ = v; n--; } + + // Bulk 8-byte fill + uint64_t v8 = v; + v8 |= v8 << 8; v8 |= v8 << 16; v8 |= v8 << 32; + auto* d8 = (uint64_t*)d; + uint64_t words = n / 8; + for (uint64_t i = 0; i < words; i++) d8[i] = v8; + + // Remainder + d = (uint8_t*)(d8 + words); + for (uint64_t i = 0; i < (n & 7); i++) d[i] = v; + } + + inline void strcpy(char* dst, const char* src) { + while (*src) *dst++ = *src++; + *dst = '\0'; + } + + inline void strncpy(char* dst, const char* src, int max) { + if (max <= 0) return; + int i = 0; + while (src[i] && i < max - 1) { dst[i] = src[i]; i++; } + dst[i] = '\0'; + } + +} diff --git a/template/sysroot/include/montauk/syscall.h b/template/sysroot/include/montauk/syscall.h new file mode 100644 index 0000000..148a92b --- /dev/null +++ b/template/sysroot/include/montauk/syscall.h @@ -0,0 +1,432 @@ +/* + * syscall.h + * MontaukOS program-side syscall wrappers using SYSCALL instruction + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include + +namespace montauk { + + // ---- Raw SYSCALL wrappers ---- + + // The SYSCALL handler does not restore RDI, RSI, RDX, R10, R8, R9 + // (they are skipped on the return path). We move arguments into the + // correct registers inside the asm block and list ALL argument + // registers in the clobber list. This guarantees the compiler + // reloads every argument on each call — GCC cannot optimise away + // clobbers, unlike "+r" outputs whose dead values it may discard. + + inline int64_t syscall0(uint64_t nr) { + int64_t ret; + asm volatile("syscall" : "=a"(ret) : "a"(nr) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall1(uint64_t nr, uint64_t a1) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall2(uint64_t nr, uint64_t a1, uint64_t a2) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "mov %[a2], %%rsi\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1), [a2] "r"(a2) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall3(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "mov %[a2], %%rsi\n\t" + "mov %[a3], %%rdx\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1), [a2] "r"(a2), [a3] "r"(a3) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall4(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "mov %[a2], %%rsi\n\t" + "mov %[a3], %%rdx\n\t" + "mov %[a4], %%r10\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1), [a2] "r"(a2), [a3] "r"(a3), [a4] "r"(a4) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall5(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "mov %[a2], %%rsi\n\t" + "mov %[a3], %%rdx\n\t" + "mov %[a4], %%r10\n\t" + "mov %[a5], %%r8\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1), [a2] "r"(a2), [a3] "r"(a3), [a4] "r"(a4), [a5] "r"(a5) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + inline int64_t syscall6(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + int64_t ret; + asm volatile( + "mov %[a1], %%rdi\n\t" + "mov %[a2], %%rsi\n\t" + "mov %[a3], %%rdx\n\t" + "mov %[a4], %%r10\n\t" + "mov %[a5], %%r8\n\t" + "mov %[a6], %%r9\n\t" + "syscall" + : "=a"(ret) + : "a"(nr), [a1] "r"(a1), [a2] "r"(a2), [a3] "r"(a3), [a4] "r"(a4), [a5] "r"(a5), [a6] "r"(a6) + : "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory"); + return ret; + } + + // ---- Typed wrappers ---- + + // Process + [[noreturn]] inline void exit(int code = 0) { + syscall1(Montauk::SYS_EXIT, (uint64_t)code); + __builtin_unreachable(); + } + + inline void yield() { syscall0(Montauk::SYS_YIELD); } + inline void sleep_ms(uint64_t ms) { syscall1(Montauk::SYS_SLEEP_MS, ms); } + inline int getpid() { return (int)syscall0(Montauk::SYS_GETPID); } + inline int spawn(const char* path, const char* args = nullptr) { + return (int)syscall2(Montauk::SYS_SPAWN, (uint64_t)path, (uint64_t)args); + } + + // Console + inline void print(const char* text) { syscall1(Montauk::SYS_PRINT, (uint64_t)text); } + inline void putchar(char c) { syscall1(Montauk::SYS_PUTCHAR, (uint64_t)c); } + + // File I/O + inline int open(const char* path) { return (int)syscall1(Montauk::SYS_OPEN, (uint64_t)path); } + inline int read(int handle, uint8_t* buf, uint64_t off, uint64_t size) { + return (int)syscall4(Montauk::SYS_READ, (uint64_t)handle, (uint64_t)buf, off, size); + } + inline uint64_t getsize(int handle) { return (uint64_t)syscall1(Montauk::SYS_GETSIZE, (uint64_t)handle); } + inline void close(int handle) { syscall1(Montauk::SYS_CLOSE, (uint64_t)handle); } + inline int readdir(const char* path, const char** names, int max) { + return (int)syscall3(Montauk::SYS_READDIR, (uint64_t)path, (uint64_t)names, (uint64_t)max); + } + + // File write/create + inline int fwrite(int handle, const uint8_t* buf, uint64_t off, uint64_t size) { + return (int)syscall4(Montauk::SYS_FWRITE, (uint64_t)handle, (uint64_t)buf, off, size); + } + inline int fcreate(const char* path) { + return (int)syscall1(Montauk::SYS_FCREATE, (uint64_t)path); + } + inline int fdelete(const char* path) { + return (int)syscall1(Montauk::SYS_FDELETE, (uint64_t)path); + } + inline int fmkdir(const char* path) { + return (int)syscall1(Montauk::SYS_FMKDIR, (uint64_t)path); + } + inline int drivelist(int* outDrives, int max) { + return (int)syscall2(Montauk::SYS_DRIVELIST, (uint64_t)outDrives, (uint64_t)max); + } + + // Memory + inline void* alloc(uint64_t size) { return (void*)syscall1(Montauk::SYS_ALLOC, size); } + inline void free(void* ptr) { syscall1(Montauk::SYS_FREE, (uint64_t)ptr); } + + // Timekeeping + inline uint64_t get_ticks() { return (uint64_t)syscall0(Montauk::SYS_GETTICKS); } + inline uint64_t get_milliseconds() { return (uint64_t)syscall0(Montauk::SYS_GETMILLISECONDS); } + + // System + inline void get_info(Montauk::SysInfo* info) { syscall1(Montauk::SYS_GETINFO, (uint64_t)info); } + + // Keyboard + inline bool is_key_available() { return (bool)syscall0(Montauk::SYS_ISKEYAVAILABLE); } + inline void getkey(Montauk::KeyEvent* out) { syscall1(Montauk::SYS_GETKEY, (uint64_t)out); } + inline char getchar() { return (char)syscall0(Montauk::SYS_GETCHAR); } + + // Networking + inline int32_t ping(uint32_t ip, uint32_t timeoutMs = 3000) { + return (int32_t)syscall2(Montauk::SYS_PING, (uint64_t)ip, (uint64_t)timeoutMs); + } + + // DNS resolve: returns IP in network byte order, or 0 on failure + inline uint32_t resolve(const char* hostname) { + return (uint32_t)syscall1(Montauk::SYS_RESOLVE, (uint64_t)hostname); + } + + // Network configuration + inline void get_netcfg(Montauk::NetCfg* out) { syscall1(Montauk::SYS_GETNETCFG, (uint64_t)out); } + inline int set_netcfg(const Montauk::NetCfg* cfg) { return (int)syscall1(Montauk::SYS_SETNETCFG, (uint64_t)cfg); } + + // Sockets + inline int socket(int type) { + return (int)syscall1(Montauk::SYS_SOCKET, (uint64_t)type); + } + inline int connect(int fd, uint32_t ip, uint16_t port) { + return (int)syscall3(Montauk::SYS_CONNECT, (uint64_t)fd, (uint64_t)ip, (uint64_t)port); + } + inline int bind(int fd, uint16_t port) { + return (int)syscall2(Montauk::SYS_BIND, (uint64_t)fd, (uint64_t)port); + } + inline int listen(int fd) { + return (int)syscall1(Montauk::SYS_LISTEN, (uint64_t)fd); + } + inline int accept(int fd) { + return (int)syscall1(Montauk::SYS_ACCEPT, (uint64_t)fd); + } + inline int send(int fd, const void* data, uint32_t len) { + return (int)syscall3(Montauk::SYS_SEND, (uint64_t)fd, (uint64_t)data, (uint64_t)len); + } + inline int recv(int fd, void* buf, uint32_t maxLen) { + return (int)syscall3(Montauk::SYS_RECV, (uint64_t)fd, (uint64_t)buf, (uint64_t)maxLen); + } + inline int closesocket(int fd) { + return (int)syscall1(Montauk::SYS_CLOSESOCK, (uint64_t)fd); + } + inline int sendto(int fd, const void* data, uint32_t len, uint32_t destIp, uint16_t destPort) { + return (int)syscall5(Montauk::SYS_SENDTO, (uint64_t)fd, (uint64_t)data, + (uint64_t)len, (uint64_t)destIp, (uint64_t)destPort); + } + inline int recvfrom(int fd, void* buf, uint32_t maxLen, uint32_t* srcIp, uint16_t* srcPort) { + return (int)syscall5(Montauk::SYS_RECVFROM, (uint64_t)fd, (uint64_t)buf, + (uint64_t)maxLen, (uint64_t)srcIp, (uint64_t)srcPort); + } + + // Process management + inline void waitpid(int pid) { syscall1(Montauk::SYS_WAITPID, (uint64_t)pid); } + + // Framebuffer + inline void fb_info(Montauk::FbInfo* info) { syscall1(Montauk::SYS_FBINFO, (uint64_t)info); } + inline void* fb_map() { return (void*)syscall0(Montauk::SYS_FBMAP); } + + // Arguments + inline int getargs(char* buf, uint64_t maxLen) { + return (int)syscall2(Montauk::SYS_GETARGS, (uint64_t)buf, maxLen); + } + + // Terminal + inline void termsize(int* cols, int* rows) { + uint64_t r = (uint64_t)syscall0(Montauk::SYS_TERMSIZE); + if (cols) *cols = (int)(r & 0xFFFFFFFF); + if (rows) *rows = (int)(r >> 32); + } + + inline void termscale(int scale_x, int scale_y) { + syscall2(Montauk::SYS_TERMSCALE, (uint64_t)scale_x, (uint64_t)scale_y); + } + + inline void get_termscale(int* scale_x, int* scale_y) { + uint64_t r = (uint64_t)syscall2(Montauk::SYS_TERMSCALE, 0, 0); + if (scale_x) *scale_x = (int)(r & 0xFFFFFFFF); + if (scale_y) *scale_y = (int)(r >> 32); + } + + // Timekeeping (wall-clock) + inline void gettime(Montauk::DateTime* out) { syscall1(Montauk::SYS_GETTIME, (uint64_t)out); } + + // Random number generation + inline int64_t getrandom(void* buf, uint32_t len) { + return syscall2(Montauk::SYS_GETRANDOM, (uint64_t)buf, (uint64_t)len); + } + + // Power management + [[noreturn]] inline void reset() { + syscall0(Montauk::SYS_RESET); + __builtin_unreachable(); + } + + [[noreturn]] inline void shutdown() { + syscall0(Montauk::SYS_SHUTDOWN); + __builtin_unreachable(); + } + + // Mouse + inline void mouse_state(Montauk::MouseState* out) { syscall1(Montauk::SYS_MOUSESTATE, (uint64_t)out); } + inline void set_mouse_bounds(int32_t maxX, int32_t maxY) { + syscall2(Montauk::SYS_SETMOUSEBOUNDS, (uint64_t)maxX, (uint64_t)maxY); + } + + // Kernel log + inline int64_t read_klog(char* buf, uint64_t size) { + return syscall2(Montauk::SYS_KLOG, (uint64_t)buf, size); + } + + // I/O redirection + inline int spawn_redir(const char* path, const char* args = nullptr) { + return (int)syscall2(Montauk::SYS_SPAWN_REDIR, (uint64_t)path, (uint64_t)args); + } + inline int childio_read(int childPid, char* buf, int maxLen) { + return (int)syscall3(Montauk::SYS_CHILDIO_READ, (uint64_t)childPid, (uint64_t)buf, (uint64_t)maxLen); + } + inline int childio_write(int childPid, const char* data, int len) { + return (int)syscall3(Montauk::SYS_CHILDIO_WRITE, (uint64_t)childPid, (uint64_t)data, (uint64_t)len); + } + inline int childio_writekey(int childPid, const Montauk::KeyEvent* key) { + return (int)syscall2(Montauk::SYS_CHILDIO_WRITEKEY, (uint64_t)childPid, (uint64_t)key); + } + inline int childio_settermsz(int childPid, int cols, int rows) { + return (int)syscall3(Montauk::SYS_CHILDIO_SETTERMSZ, (uint64_t)childPid, (uint64_t)cols, (uint64_t)rows); + } + + // Process listing / kill + inline int proclist(Montauk::ProcInfo* buf, int max) { + return (int)syscall2(Montauk::SYS_PROCLIST, (uint64_t)buf, (uint64_t)max); + } + inline int kill(int pid) { + return (int)syscall1(Montauk::SYS_KILL, (uint64_t)pid); + } + inline int devlist(Montauk::DevInfo* buf, int max) { + return (int)syscall2(Montauk::SYS_DEVLIST, (uint64_t)buf, (uint64_t)max); + } + inline int diskinfo(Montauk::DiskInfo* buf, int port) { + return (int)syscall2(Montauk::SYS_DISKINFO, (uint64_t)buf, (uint64_t)port); + } + + // Partition table + inline int partlist(Montauk::PartInfo* buf, int max) { + return (int)syscall2(Montauk::SYS_PARTLIST, (uint64_t)buf, (uint64_t)max); + } + + // Raw block device I/O (driver-agnostic) + inline int64_t disk_read(int blockDev, uint64_t lba, uint32_t sectorCount, void* buf) { + return syscall4(Montauk::SYS_DISKREAD, (uint64_t)blockDev, lba, + (uint64_t)sectorCount, (uint64_t)buf); + } + inline int64_t disk_write(int blockDev, uint64_t lba, uint32_t sectorCount, const void* buf) { + return syscall4(Montauk::SYS_DISKWRITE, (uint64_t)blockDev, lba, + (uint64_t)sectorCount, (uint64_t)buf); + } + + // GPT management + inline int gpt_init(int blockDev) { + return (int)syscall1(Montauk::SYS_GPTINIT, (uint64_t)blockDev); + } + inline int gpt_add(const Montauk::GptAddParams* params) { + return (int)syscall1(Montauk::SYS_GPTADD, (uint64_t)params); + } + inline int fs_mount(int partIndex, int driveNum) { + return (int)syscall2(Montauk::SYS_FSMOUNT, (uint64_t)partIndex, (uint64_t)driveNum); + } + inline int fs_format(const Montauk::FsFormatParams* params) { + return (int)syscall1(Montauk::SYS_FSFORMAT, (uint64_t)params); + } + + // Audio + inline int audio_open(uint32_t sampleRate, uint8_t channels, uint8_t bitsPerSample) { + return (int)syscall3(Montauk::SYS_AUDIOOPEN, (uint64_t)sampleRate, + (uint64_t)channels, (uint64_t)bitsPerSample); + } + inline void audio_close(int handle) { + syscall1(Montauk::SYS_AUDIOCLOSE, (uint64_t)handle); + } + inline int audio_write(int handle, const void* data, uint32_t size) { + return (int)syscall3(Montauk::SYS_AUDIOWRITE, (uint64_t)handle, + (uint64_t)data, (uint64_t)size); + } + inline int audio_ctl(int handle, int cmd, int value) { + return (int)syscall3(Montauk::SYS_AUDIOCTL, (uint64_t)handle, + (uint64_t)cmd, (uint64_t)value); + } + inline int audio_set_volume(int handle, int percent) { + return audio_ctl(handle, Montauk::AUDIO_CTL_SET_VOLUME, percent); + } + inline int audio_get_volume(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_GET_VOLUME, 0); + } + inline int audio_get_pos(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_GET_POS, 0); + } + inline int audio_pause(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_PAUSE, 1); + } + inline int audio_resume(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_PAUSE, 0); + } + inline int audio_get_output(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_GET_OUTPUT, 0); + } + inline int audio_bt_status(int handle) { + return audio_ctl(handle, Montauk::AUDIO_CTL_BT_STATUS, 0); + } + + // Bluetooth + inline int bt_scan(Montauk::BtScanResult* buf, int maxCount, uint32_t timeoutMs) { + return (int)syscall3(Montauk::SYS_BTSCAN, (uint64_t)buf, (uint64_t)maxCount, (uint64_t)timeoutMs); + } + inline int bt_connect(const uint8_t* bdAddr) { + return (int)syscall1(Montauk::SYS_BTCONNECT, (uint64_t)bdAddr); + } + inline int bt_disconnect(const uint8_t* bdAddr) { + return (int)syscall1(Montauk::SYS_BTDISCONNECT, (uint64_t)bdAddr); + } + inline int bt_list(Montauk::BtDevInfo* buf, int maxCount) { + return (int)syscall2(Montauk::SYS_BTLIST, (uint64_t)buf, (uint64_t)maxCount); + } + inline int bt_info(Montauk::BtAdapterInfo* buf) { + return (int)syscall1(Montauk::SYS_BTINFO, (uint64_t)buf); + } + + // Kernel introspection + inline void memstats(Montauk::MemStats* out) { syscall1(Montauk::SYS_MEMSTATS, (uint64_t)out); } + + // Window server + inline int win_create(const char* title, int w, int h, Montauk::WinCreateResult* result) { + return (int)syscall4(Montauk::SYS_WINCREATE, (uint64_t)title, (uint64_t)w, (uint64_t)h, (uint64_t)result); + } + inline int win_destroy(int id) { + return (int)syscall1(Montauk::SYS_WINDESTROY, (uint64_t)id); + } + inline uint64_t win_present(int id) { + return (uint64_t)syscall1(Montauk::SYS_WINPRESENT, (uint64_t)id); + } + inline int win_poll(int id, Montauk::WinEvent* event) { + return (int)syscall2(Montauk::SYS_WINPOLL, (uint64_t)id, (uint64_t)event); + } + inline int win_enumerate(Montauk::WinInfo* info, int max) { + return (int)syscall2(Montauk::SYS_WINENUM, (uint64_t)info, (uint64_t)max); + } + inline uint64_t win_map(int id) { + return (uint64_t)syscall1(Montauk::SYS_WINMAP, (uint64_t)id); + } + inline int win_sendevent(int id, const Montauk::WinEvent* event) { + return (int)syscall2(Montauk::SYS_WINSENDEVENT, (uint64_t)id, (uint64_t)event); + } + inline uint64_t win_resize(int id, int w, int h) { + return (uint64_t)syscall3(Montauk::SYS_WINRESIZE, (uint64_t)id, (uint64_t)w, (uint64_t)h); + } + inline int win_setscale(int scale) { + return (int)syscall1(Montauk::SYS_WINSETSCALE, (uint64_t)scale); + } + inline int win_getscale() { + return (int)syscall0(Montauk::SYS_WINGETSCALE); + } + inline int win_setcursor(int id, int cursor) { + return (int)syscall2(Montauk::SYS_WINSETCURSOR, (uint64_t)id, (uint64_t)cursor); + } + +} diff --git a/template/sysroot/include/montauk/toml.h b/template/sysroot/include/montauk/toml.h new file mode 100644 index 0000000..db59843 --- /dev/null +++ b/template/sysroot/include/montauk/toml.h @@ -0,0 +1,573 @@ +/* + * toml.h + * TOML config file parser + * Supports: strings, integers, booleans, tables, arrays + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include +#include +#include + +namespace montauk { +namespace toml { + + enum class Type { String, Int, Bool, Array, Table }; + + struct Value; + + // Dynamic array of Value pointers (for arrays and table entries) + struct ValueList { + Value** items; + int count; + int cap; + + void init() { items = nullptr; count = 0; cap = 0; } + + void push(Value* v) { + if (count >= cap) { + int newCap = cap ? cap * 2 : 8; + auto** buf = (Value**)montauk::malloc(newCap * sizeof(Value*)); + if (items) { + montauk::memcpy(buf, items, count * sizeof(Value*)); + montauk::mfree(items); + } + items = buf; + cap = newCap; + } + items[count++] = v; + } + + void destroy(); // forward — defined after Value + }; + + struct Value { + Type type; + char* key; // owned, dotted path (e.g. "server.port"); null for array elements + + union { + char* str; // Type::String — owned + int64_t ival; // Type::Int + bool bval; // Type::Bool + }; + ValueList array; // Type::Array elements or Type::Table entries + + static Value* make_string(const char* k, const char* s, int slen) { + auto* v = (Value*)montauk::malloc(sizeof(Value)); + v->type = Type::String; + v->key = dup(k); + v->str = dupn(s, slen); + v->array.init(); + return v; + } + + static Value* make_int(const char* k, int64_t n) { + auto* v = (Value*)montauk::malloc(sizeof(Value)); + v->type = Type::Int; + v->key = dup(k); + v->ival = n; + v->array.init(); + return v; + } + + static Value* make_bool(const char* k, bool b) { + auto* v = (Value*)montauk::malloc(sizeof(Value)); + v->type = Type::Bool; + v->key = dup(k); + v->bval = b; + v->array.init(); + return v; + } + + static Value* make_array(const char* k) { + auto* v = (Value*)montauk::malloc(sizeof(Value)); + v->type = Type::Array; + v->key = dup(k); + v->ival = 0; + v->array.init(); + return v; + } + + static Value* make_table(const char* k) { + auto* v = (Value*)montauk::malloc(sizeof(Value)); + v->type = Type::Table; + v->key = dup(k); + v->ival = 0; + v->array.init(); + return v; + } + + void destroy() { + if (key) montauk::mfree(key); + if (type == Type::String && str) montauk::mfree(str); + array.destroy(); + montauk::mfree(this); + } + + // helpers + static char* dup(const char* s) { + if (!s) return nullptr; + int n = montauk::slen(s); + return dupn(s, n); + } + static char* dupn(const char* s, int n) { + char* d = (char*)montauk::malloc(n + 1); + montauk::memcpy(d, s, n); + d[n] = '\0'; + return d; + } + }; + + inline void ValueList::destroy() { + for (int i = 0; i < count; i++) items[i]->destroy(); + if (items) montauk::mfree(items); + items = nullptr; + count = 0; + cap = 0; + } + + // ---- Document ---- + + struct Doc { + ValueList entries; // flat list of all top-level and nested values + + void init() { entries.init(); } + + void destroy() { + entries.destroy(); + } + + // Lookup by dotted key path (e.g. "server.port") + Value* get(const char* key) const { + for (int i = 0; i < entries.count; i++) { + if (entries.items[i]->key && montauk::streq(entries.items[i]->key, key)) + return entries.items[i]; + } + return nullptr; + } + + // Typed accessors with defaults + const char* get_string(const char* key, const char* def = "") const { + auto* v = get(key); + return (v && v->type == Type::String) ? v->str : def; + } + + int64_t get_int(const char* key, int64_t def = 0) const { + auto* v = get(key); + return (v && v->type == Type::Int) ? v->ival : def; + } + + bool get_bool(const char* key, bool def = false) const { + auto* v = get(key); + return (v && v->type == Type::Bool) ? v->bval : def; + } + + Value* get_array(const char* key) const { + auto* v = get(key); + return (v && v->type == Type::Array) ? v : nullptr; + } + + Value* get_table(const char* key) const { + auto* v = get(key); + return (v && v->type == Type::Table) ? v : nullptr; + } + }; + + // ---- Parser ---- + + namespace detail { + + struct Parser { + const char* src; + int pos; + int len; + char table_prefix[256]; // current [table] prefix + + char peek() const { return pos < len ? src[pos] : '\0'; } + char next() { return pos < len ? src[pos++] : '\0'; } + bool at_end() const { return pos >= len; } + + void skip_ws() { + while (pos < len && (src[pos] == ' ' || src[pos] == '\t')) pos++; + } + + void skip_line() { + while (pos < len && src[pos] != '\n') pos++; + if (pos < len) pos++; // consume newline + } + + void skip_ws_and_newlines() { + while (pos < len) { + char c = src[pos]; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + pos++; + else if (c == '#') + skip_line(); + else + break; + } + } + + // Build dotted key: prefix.key + void build_key(char* out, int outSz, const char* key, int keyLen) { + int p = 0; + if (table_prefix[0]) { + int plen = montauk::slen(table_prefix); + for (int i = 0; i < plen && p < outSz - 2; i++) out[p++] = table_prefix[i]; + out[p++] = '.'; + } + for (int i = 0; i < keyLen && p < outSz - 1; i++) out[p++] = key[i]; + out[p] = '\0'; + } + + // Parse a bare key or quoted key, returns length + int parse_key(char* buf, int bufSz) { + skip_ws(); + int n = 0; + if (peek() == '"') { + next(); // consume opening quote + while (!at_end() && peek() != '"' && n < bufSz - 1) + buf[n++] = next(); + if (peek() == '"') next(); + } else { + while (!at_end()) { + char c = peek(); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '_' || c == '-') { + buf[n++] = next(); + if (n >= bufSz - 1) break; + } else { + break; + } + } + } + buf[n] = '\0'; + return n; + } + + // Parse a dotted key (e.g. server.host), returns full length written to buf + int parse_dotted_key(char* buf, int bufSz) { + int total = 0; + // Parse first segment + char seg[128]; + int segLen = parse_key(seg, sizeof(seg)); + for (int i = 0; i < segLen && total < bufSz - 1; i++) + buf[total++] = seg[i]; + + // Parse additional dotted segments + while (peek() == '.') { + next(); // consume dot + if (total < bufSz - 1) buf[total++] = '.'; + segLen = parse_key(seg, sizeof(seg)); + for (int i = 0; i < segLen && total < bufSz - 1; i++) + buf[total++] = seg[i]; + } + buf[total] = '\0'; + return total; + } + + int64_t parse_integer() { + bool neg = false; + if (peek() == '-') { neg = true; next(); } + else if (peek() == '+') { next(); } + + // Hex, octal, binary + if (peek() == '0' && pos + 1 < len) { + char c2 = src[pos + 1]; + if (c2 == 'x' || c2 == 'X') { + pos += 2; + int64_t val = 0; + while (!at_end()) { + char c = peek(); + if (c == '_') { next(); continue; } + int d = -1; + if (c >= '0' && c <= '9') d = c - '0'; + else if (c >= 'a' && c <= 'f') d = 10 + c - 'a'; + else if (c >= 'A' && c <= 'F') d = 10 + c - 'A'; + if (d < 0) break; + val = val * 16 + d; + next(); + } + return neg ? -val : val; + } + if (c2 == 'o') { + pos += 2; + int64_t val = 0; + while (!at_end()) { + char c = peek(); + if (c == '_') { next(); continue; } + if (c < '0' || c > '7') break; + val = val * 8 + (c - '0'); + next(); + } + return neg ? -val : val; + } + if (c2 == 'b') { + pos += 2; + int64_t val = 0; + while (!at_end()) { + char c = peek(); + if (c == '_') { next(); continue; } + if (c != '0' && c != '1') break; + val = val * 2 + (c - '0'); + next(); + } + return neg ? -val : val; + } + } + + int64_t val = 0; + while (!at_end()) { + char c = peek(); + if (c == '_') { next(); continue; } + if (c < '0' || c > '9') break; + val = val * 10 + (c - '0'); + next(); + } + return neg ? -val : val; + } + + // Parse string value (opening quote already detected but not consumed) + // Returns heap-allocated string + char* parse_string_value(int* outLen) { + char quote = next(); // consume opening " or ' + bool literal = (quote == '\''); + + // Multi-line? (""" or ''') + bool multi = false; + if (pos + 1 < len && src[pos] == quote && src[pos + 1] == quote) { + pos += 2; + multi = true; + // Skip first newline after opening delimiter + if (peek() == '\r') next(); + if (peek() == '\n') next(); + } + + // Collect into temp buffer + char buf[4096]; + int n = 0; + + while (!at_end() && n < (int)sizeof(buf) - 1) { + if (multi) { + // Check for closing triple-quote + if (pos + 2 < len && src[pos] == quote && + src[pos+1] == quote && src[pos+2] == quote) { + pos += 3; + break; + } + } else { + if (peek() == quote) { next(); break; } + if (peek() == '\n') break; // unterminated single-line + } + + if (!literal && peek() == '\\') { + next(); // consume backslash + char esc = next(); + switch (esc) { + case 'n': buf[n++] = '\n'; break; + case 't': buf[n++] = '\t'; break; + case 'r': buf[n++] = '\r'; break; + case '\\': buf[n++] = '\\'; break; + case '"': buf[n++] = '"'; break; + case '\r': + if (peek() == '\n') next(); + skip_ws(); + break; + case '\n': + skip_ws(); + break; + default: buf[n++] = esc; break; + } + } else { + buf[n++] = next(); + } + } + + *outLen = n; + return Value::dupn(buf, n); + } + + Value* parse_value(const char* fullKey) { + skip_ws(); + char c = peek(); + + // String + if (c == '"' || c == '\'') { + int slen = 0; + char* s = parse_string_value(&slen); + auto* v = Value::make_string(fullKey, s, slen); + montauk::mfree(s); + return v; + } + + // Boolean + if (montauk::starts_with(src + pos, "true")) { + pos += 4; + return Value::make_bool(fullKey, true); + } + if (montauk::starts_with(src + pos, "false")) { + pos += 5; + return Value::make_bool(fullKey, false); + } + + // Array + if (c == '[') { + next(); // consume [ + auto* arr = Value::make_array(fullKey); + skip_ws_and_newlines(); + while (!at_end() && peek() != ']') { + auto* elem = parse_value(nullptr); + if (elem) arr->array.push(elem); + skip_ws_and_newlines(); + if (peek() == ',') next(); + skip_ws_and_newlines(); + } + if (peek() == ']') next(); + return arr; + } + + // Inline table + if (c == '{') { + next(); // consume { + auto* tbl = Value::make_table(fullKey); + skip_ws_and_newlines(); + while (!at_end() && peek() != '}') { + char key[128]; + int keyLen = parse_dotted_key(key, sizeof(key)); + if (keyLen == 0) { skip_line(); continue; } + skip_ws(); + if (peek() == '=') next(); + skip_ws(); + + // Build full dotted key for inline table entry + char entryKey[256]; + int p = 0; + if (fullKey) { + int flen = montauk::slen(fullKey); + for (int i = 0; i < flen && p < 254; i++) entryKey[p++] = fullKey[i]; + entryKey[p++] = '.'; + } + for (int i = 0; i < keyLen && p < 255; i++) entryKey[p++] = key[i]; + entryKey[p] = '\0'; + + auto* val = parse_value(entryKey); + if (val) tbl->array.push(val); + skip_ws(); + if (peek() == ',') next(); + skip_ws(); + } + if (peek() == '}') next(); + return tbl; + } + + // Integer (includes negative) + if ((c >= '0' && c <= '9') || c == '+' || c == '-') { + int64_t n = parse_integer(); + return Value::make_int(fullKey, n); + } + + // Unknown — skip the rest of the line + skip_line(); + return nullptr; + } + + void parse(Doc* doc) { + table_prefix[0] = '\0'; + + while (!at_end()) { + skip_ws_and_newlines(); + if (at_end()) break; + + char c = peek(); + + // Table header: [name] or [name.sub] + if (c == '[') { + next(); + bool array_table = false; + if (peek() == '[') { next(); array_table = true; } + + skip_ws(); + int plen = parse_dotted_key(table_prefix, sizeof(table_prefix)); + skip_ws(); + if (peek() == ']') next(); + if (array_table && peek() == ']') next(); + + // Register the table itself + auto* tbl = Value::make_table(table_prefix); + doc->entries.push(tbl); + + skip_line(); + continue; + } + + // Key = value + char key[128]; + int keyLen = parse_dotted_key(key, sizeof(key)); + if (keyLen == 0) { skip_line(); continue; } + + skip_ws(); + if (peek() != '=') { skip_line(); continue; } + next(); // consume = + skip_ws(); + + char fullKey[256]; + build_key(fullKey, sizeof(fullKey), key, keyLen); + + Value* val = parse_value(fullKey); + if (val) { + doc->entries.push(val); + + // For inline tables, also flatten entries into doc + if (val->type == Type::Table) { + for (int i = 0; i < val->array.count; i++) { + // Clone entry into doc's flat list so dotted lookup works + auto* e = val->array.items[i]; + Value* clone = nullptr; + if (e->type == Type::String) + clone = Value::make_string(e->key, e->str, montauk::slen(e->str)); + else if (e->type == Type::Int) + clone = Value::make_int(e->key, e->ival); + else if (e->type == Type::Bool) + clone = Value::make_bool(e->key, e->bval); + if (clone) doc->entries.push(clone); + } + } + } + + // Consume rest of line (trailing comment, etc.) + skip_ws(); + if (peek() == '#') skip_line(); + else if (peek() == '\r' || peek() == '\n') { + if (peek() == '\r') next(); + if (peek() == '\n') next(); + } + } + } + }; + + } // namespace detail + + // ---- Public API ---- + + // Parse a TOML string into a Doc. Caller must call doc.destroy() when done. + inline Doc parse(const char* text) { + Doc doc; + doc.init(); + + detail::Parser p; + p.src = text; + p.pos = 0; + p.len = montauk::slen(text); + p.table_prefix[0] = '\0'; + p.parse(&doc); + + return doc; + } + + // Parse from a file descriptor (reads entire file into buffer first). + // Requires montauk::syscall read/fstat or similar — omitted here for portability. + // Users can read a file into a buffer and call parse() directly. + +} // namespace toml +} // namespace montauk diff --git a/template/sysroot/include/montauk/user.h b/template/sysroot/include/montauk/user.h new file mode 100644 index 0000000..0324ecd --- /dev/null +++ b/template/sysroot/include/montauk/user.h @@ -0,0 +1,338 @@ +/* + * user.h + * User database, password hashing, and authentication for MontaukOS + * Copyright (c) 2026 Daniel Hammer +*/ + +#pragma once +#include +#include +#include +#include +#include + +namespace montauk { +namespace user { + + static constexpr int MAX_USERS = 16; + + struct UserInfo { + char username[32]; + char display_name[64]; + char password_hash[65]; // 64 hex chars + null + char salt[33]; // 32 hex chars + null + char role[16]; + }; + + // ---- String helpers ---- + + inline void str_cat(char* dst, const char* src, int max) { + int len = montauk::slen(dst); + int i = 0; + while (src[i] && len < max - 1) { + dst[len++] = src[i++]; + } + dst[len] = '\0'; + } + + inline void build_user_key(char* out, int sz, const char* username, const char* field) { + int p = 0; + const char* prefix = "users."; + while (*prefix && p < sz - 1) out[p++] = *prefix++; + while (*username && p < sz - 1) out[p++] = *username++; + if (p < sz - 1) out[p++] = '.'; + while (*field && p < sz - 1) out[p++] = *field++; + out[p] = '\0'; + } + + // ---- Path helpers ---- + + inline void home_dir(const char* username, char* out, int sz) { + int p = 0; + const char* prefix = "0:/users/"; + while (*prefix && p < sz - 1) out[p++] = *prefix++; + while (*username && p < sz - 1) out[p++] = *username++; + out[p] = '\0'; + } + + inline void config_dir(const char* username, char* out, int sz) { + home_dir(username, out, sz); + str_cat(out, "/config", sz); + } + + // ---- Hex conversion helpers ---- + + inline void bytes_to_hex(const uint8_t* bytes, int len, char* out) { + const char* digits = "0123456789abcdef"; + for (int i = 0; i < len; i++) { + out[i * 2] = digits[(bytes[i] >> 4) & 0x0F]; + out[i * 2 + 1] = digits[bytes[i] & 0x0F]; + } + out[len * 2] = '\0'; + } + + inline int hex_char_val(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return 10 + c - 'a'; + if (c >= 'A' && c <= 'F') return 10 + c - 'A'; + return -1; + } + + inline int hex_to_bytes(const char* hex, uint8_t* out, int maxBytes) { + int i = 0; + while (hex[i * 2] && hex[i * 2 + 1] && i < maxBytes) { + int hi = hex_char_val(hex[i * 2]); + int lo = hex_char_val(hex[i * 2 + 1]); + if (hi < 0 || lo < 0) return i; + out[i] = (uint8_t)((hi << 4) | lo); + i++; + } + return i; + } + + // ---- Password hashing (SHA-256) ---- + + inline void hash_password(const char* password, const char* salt_hex, char* out_hex64) { + uint8_t salt_bytes[16]; + int salt_len = hex_to_bytes(salt_hex, salt_bytes, 16); + int pass_len = montauk::slen(password); + + br_sha256_context ctx; + br_sha256_init(&ctx); + br_sha256_update(&ctx, salt_bytes, salt_len); + br_sha256_update(&ctx, password, pass_len); + + uint8_t hash[32]; + br_sha256_out(&ctx, hash); + bytes_to_hex(hash, 32, out_hex64); + } + + inline bool verify_password(const char* password, const char* salt_hex, const char* stored_hex64) { + char computed[65]; + hash_password(password, salt_hex, computed); + + int diff = 0; + for (int i = 0; i < 64; i++) { + diff |= computed[i] ^ stored_hex64[i]; + } + return diff == 0; + } + + // ---- User database I/O ---- + + inline int load_users(UserInfo* buf, int max) { + auto doc = config::load("users"); + int count = 0; + + for (int i = 0; i < doc.entries.count && count < max; i++) { + auto* v = doc.entries.items[i]; + if (!v->key) continue; + + if (!montauk::starts_with(v->key, "users.")) continue; + const char* after = v->key + 6; + + int dot = -1; + for (int j = 0; after[j]; j++) { + if (after[j] == '.') { dot = j; break; } + } + if (dot <= 0) continue; + + if (!montauk::streq(after + dot + 1, "display_name")) continue; + + UserInfo* u = &buf[count]; + montauk::memset(u, 0, sizeof(UserInfo)); + int ulen = dot < 31 ? dot : 31; + montauk::memcpy(u->username, after, ulen); + u->username[ulen] = '\0'; + + if (v->type == montauk::toml::Type::String && v->str) + montauk::strncpy(u->display_name, v->str, sizeof(u->display_name)); + + char prefix[64]; + int plen = 0; + const char* pfx = "users."; + while (*pfx) prefix[plen++] = *pfx++; + for (int j = 0; j < ulen; j++) prefix[plen++] = u->username[j]; + prefix[plen] = '\0'; + + char key[96]; + + montauk::strcpy(key, prefix); + str_cat(key, ".password_hash", 96); + const char* ph = doc.get_string(key, ""); + montauk::strncpy(u->password_hash, ph, sizeof(u->password_hash)); + + montauk::strcpy(key, prefix); + str_cat(key, ".salt", 96); + const char* s = doc.get_string(key, ""); + montauk::strncpy(u->salt, s, sizeof(u->salt)); + + montauk::strcpy(key, prefix); + str_cat(key, ".role", 96); + const char* r = doc.get_string(key, "user"); + montauk::strncpy(u->role, r, sizeof(u->role)); + + count++; + } + + doc.destroy(); + return count; + } + + inline int save_users(const UserInfo* buf, int count) { + montauk::toml::Doc doc; + doc.init(); + + for (int i = 0; i < count; i++) { + const UserInfo* u = &buf[i]; + char key[96]; + + build_user_key(key, 96, u->username, "display_name"); + config::set_string(&doc, key, u->display_name); + + build_user_key(key, 96, u->username, "password_hash"); + config::set_string(&doc, key, u->password_hash); + + build_user_key(key, 96, u->username, "salt"); + config::set_string(&doc, key, u->salt); + + build_user_key(key, 96, u->username, "role"); + config::set_string(&doc, key, u->role); + } + + int ret = config::save("users", &doc); + doc.destroy(); + return ret; + } + + // ---- Authentication ---- + + inline bool authenticate(const char* username, const char* password) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { + return verify_password(password, users[i].salt, users[i].password_hash); + } + } + return false; + } + + // ---- User management ---- + + inline bool create_user(const char* username, const char* display_name, + const char* password, const char* role) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) return false; + } + if (count >= MAX_USERS) return false; + + UserInfo* u = &users[count]; + montauk::memset(u, 0, sizeof(UserInfo)); + montauk::strncpy(u->username, username, 31); + montauk::strncpy(u->display_name, display_name, 63); + montauk::strncpy(u->role, role, 15); + + uint8_t salt_bytes[16]; + montauk::getrandom(salt_bytes, 16); + bytes_to_hex(salt_bytes, 16, u->salt); + + hash_password(password, u->salt, u->password_hash); + + count++; + save_users(users, count); + + // Create home directory structure + char dir[128]; + home_dir(username, dir, sizeof(dir)); + montauk::fmkdir(dir); + + char subdir[128]; + montauk::strcpy(subdir, dir); + str_cat(subdir, "/config", 128); + montauk::fmkdir(subdir); + + return true; + } + + inline bool delete_user(const char* username) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + int idx = -1; + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { idx = i; break; } + } + if (idx < 0) return false; + + for (int i = idx; i < count - 1; i++) { + users[i] = users[i + 1]; + } + count--; + + save_users(users, count); + return true; + } + + inline bool change_password(const char* username, const char* new_password) { + UserInfo users[MAX_USERS]; + int count = load_users(users, MAX_USERS); + + for (int i = 0; i < count; i++) { + if (montauk::streq(users[i].username, username)) { + uint8_t salt_bytes[16]; + montauk::getrandom(salt_bytes, 16); + bytes_to_hex(salt_bytes, 16, users[i].salt); + + hash_password(new_password, users[i].salt, users[i].password_hash); + + save_users(users, count); + return true; + } + } + return false; + } + + // ---- Session (current logged-in user) ---- + + // Write the current session after successful login. + // Stores username in 0:/config/session.toml so any app can query it. + inline void set_session(const char* username) { + montauk::toml::Doc doc; + doc.init(); + config::set_string(&doc, "session.username", username); + config::save("session", &doc); + doc.destroy(); + } + + // Clear the session (on logout). + inline void clear_session() { + montauk::fdelete("0:/config/session.toml"); + } + + // Read the current username into buf. Returns true if a session exists. + inline bool get_session_username(char* buf, int bufSz) { + auto doc = config::load("session"); + const char* name = doc.get_string("session.username", ""); + bool found = (name[0] != '\0'); + if (found) { + montauk::strncpy(buf, name, bufSz); + } + doc.destroy(); + return found; + } + + // Get the current user's home directory. Returns true if a session exists. + inline bool get_home_dir(char* buf, int bufSz) { + char username[32]; + if (!get_session_username(username, sizeof(username))) return false; + home_dir(username, buf, bufSz); + return true; + } + +} // namespace user +} // namespace montauk diff --git a/template/sysroot/include/movdirintrin.h b/template/sysroot/include/movdirintrin.h new file mode 100644 index 0000000..9655bf0 --- /dev/null +++ b/template/sysroot/include/movdirintrin.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _MOVDIRINTRIN_H_INCLUDED +#define _MOVDIRINTRIN_H_INCLUDED + +#ifndef __MOVDIRI__ +#pragma GCC push_options +#pragma GCC target ("movdiri") +#define __DISABLE_MOVDIRI__ +#endif /* __MOVDIRI__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_directstoreu_u32 (void * __P, unsigned int __A) +{ + __builtin_ia32_directstoreu_u32 ((unsigned int *)__P, __A); +} +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_directstoreu_u64 (void * __P, unsigned long long __A) +{ + __builtin_ia32_directstoreu_u64 ((unsigned long long *)__P, __A); +} +#endif + +#ifdef __DISABLE_MOVDIRI__ +#undef __DISABLE_MOVDIRI__ +#pragma GCC pop_options +#endif /* __DISABLE_MOVDIRI__ */ + +#ifndef __MOVDIR64B__ +#pragma GCC push_options +#pragma GCC target ("movdir64b") +#define __DISABLE_MOVDIR64B__ +#endif /* __MOVDIR64B__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_movdir64b (void * __P, const void * __Q) +{ + __builtin_ia32_movdir64b (__P, __Q); +} + +#ifdef __DISABLE_MOVDIR64B__ +#undef __DISABLE_MOVDIR64B__ +#pragma GCC pop_options +#endif /* __DISABLE_MOVDIR64B__ */ +#endif /* _MOVDIRINTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/mwaitintrin.h b/template/sysroot/include/mwaitintrin.h new file mode 100644 index 0000000..a0e9bb2 --- /dev/null +++ b/template/sysroot/include/mwaitintrin.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2021-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _MWAITINTRIN_H_INCLUDED +#define _MWAITINTRIN_H_INCLUDED + +#ifndef __MWAIT__ +#pragma GCC push_options +#pragma GCC target("mwait") +#define __DISABLE_MWAIT__ +#endif /* __MWAIT__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_monitor (void const * __P, unsigned int __E, unsigned int __H) +{ + __builtin_ia32_monitor (__P, __E, __H); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mwait (unsigned int __E, unsigned int __H) +{ + __builtin_ia32_mwait (__E, __H); +} + +#ifdef __DISABLE_MWAIT__ +#undef __DISABLE_MWAIT__ +#pragma GCC pop_options +#endif /* __DISABLE_MWAIT__ */ + +#endif /* _MWAITINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/mwaitxintrin.h b/template/sysroot/include/mwaitxintrin.h new file mode 100644 index 0000000..c9d1af4 --- /dev/null +++ b/template/sysroot/include/mwaitxintrin.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _MWAITXINTRIN_H_INCLUDED +#define _MWAITXINTRIN_H_INCLUDED + +#ifndef __MWAITX__ +#pragma GCC push_options +#pragma GCC target("mwaitx") +#define __DISABLE_MWAITX__ +#endif /* __MWAITX__ */ + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_monitorx (void const * __P, unsigned int __E, unsigned int __H) +{ + __builtin_ia32_monitorx (__P, __E, __H); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mwaitx (unsigned int __E, unsigned int __H, unsigned int __C) +{ + __builtin_ia32_mwaitx (__E, __H, __C); +} + +#ifdef __DISABLE_MWAITX__ +#undef __DISABLE_MWAITX__ +#pragma GCC pop_options +#endif /* __DISABLE_MWAITX__ */ + +#endif /* _MWAITXINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/new b/template/sysroot/include/new new file mode 100644 index 0000000..8b07150 --- /dev/null +++ b/template/sysroot/include/new @@ -0,0 +1,238 @@ +// The -*- C++ -*- dynamic memory management header. + +// Copyright (C) 1994-2024 Free Software Foundation, Inc. + +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file new + * This is a Standard C++ Library header. + * + * The header @c new defines several functions to manage dynamic memory and + * handling memory allocation errors; see + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html + * for more. + */ + +#ifndef _NEW +#define _NEW + +#pragma GCC system_header + +#include +#include + +#define __glibcxx_want_launder +#define __glibcxx_want_hardware_interference_size +#define __glibcxx_want_destroying_delete +#include + +#pragma GCC visibility push(default) + +extern "C++" { + +namespace std +{ + /** + * @brief Exception possibly thrown by @c new. + * @ingroup exceptions + * + * @c bad_alloc (or classes derived from it) is used to report allocation + * errors from the throwing forms of @c new. */ + class bad_alloc : public exception + { + public: + bad_alloc() throw() { } + +#if __cplusplus >= 201103L + bad_alloc(const bad_alloc&) = default; + bad_alloc& operator=(const bad_alloc&) = default; +#endif + + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_alloc() throw(); + + // See comment in eh_exception.cc. + virtual const char* what() const throw(); + }; + +#if __cplusplus >= 201103L + class bad_array_new_length : public bad_alloc + { + public: + bad_array_new_length() throw() { } + + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_array_new_length() throw(); + + // See comment in eh_exception.cc. + virtual const char* what() const throw(); + }; +#endif + +#if __cpp_aligned_new + enum class align_val_t: size_t {}; +#endif + + struct nothrow_t + { +#if __cplusplus >= 201103L + explicit nothrow_t() = default; +#endif + }; + + extern const nothrow_t nothrow; + + /** If you write your own error handler to be called by @c new, it must + * be of this type. */ + typedef void (*new_handler)(); + + /// Takes a replacement handler as the argument, returns the + /// previous handler. + new_handler set_new_handler(new_handler) throw(); + +#if __cplusplus >= 201103L + /// Return the current new handler. + new_handler get_new_handler() noexcept; +#endif +} // namespace std + +//@{ +/** These are replaceable signatures: + * - normal single new and delete (no arguments, throw @c bad_alloc on error) + * - normal array new and delete (same) + * - @c nothrow single new and delete (take a @c nothrow argument, return + * @c NULL on error) + * - @c nothrow array new and delete (same) + * + * Placement new and delete signatures (take a memory address argument, + * does nothing) may not be replaced by a user's program. +*/ +_GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +void operator delete(void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#endif +_GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if __cpp_aligned_new +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +void operator delete(void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete(void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); +void operator delete[](void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#endif // __cpp_sized_deallocation +#endif // __cpp_aligned_new + +// Default placement versions of operator new. +_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } +_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } + +// Default placement versions of operator delete. +inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { } +inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } +//@} +} // extern "C++" + +#if __cplusplus >= 201703L +namespace std +{ +#ifdef __cpp_lib_launder // C++ >= 17 && HAVE_BUILTIN_LAUNDER + /// Pointer optimization barrier [ptr.launder] + template + [[nodiscard]] constexpr _Tp* + launder(_Tp* __p) noexcept + { return __builtin_launder(__p); } + + // The program is ill-formed if T is a function type or + // (possibly cv-qualified) void. + + template + void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete; + template + void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete; + + void launder(void*) = delete; + void launder(const void*) = delete; + void launder(volatile void*) = delete; + void launder(const volatile void*) = delete; +#endif // __cpp_lib_launder + +#ifdef __cpp_lib_hardware_interference_size // C++ >= 17 && defined(gcc_dest_sz) + inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE; + inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE; +#endif // __cpp_lib_hardware_interference_size +} +#endif // C++17 + +// Emitted despite the FTM potentially being undefined. +#if __cplusplus > 201703L +namespace std +{ + /// Tag type used to declare a class-specific operator delete that can + /// invoke the destructor before deallocating the memory. + struct destroying_delete_t + { + explicit destroying_delete_t() = default; + }; + /// Tag variable of type destroying_delete_t. + inline constexpr destroying_delete_t destroying_delete{}; +} +#endif // C++20 + +#pragma GCC visibility pop + +#endif diff --git a/template/sysroot/include/nmmintrin.h b/template/sysroot/include/nmmintrin.h new file mode 100644 index 0000000..3747f80 --- /dev/null +++ b/template/sysroot/include/nmmintrin.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 10.0. */ + +#ifndef _NMMINTRIN_H_INCLUDED +#define _NMMINTRIN_H_INCLUDED + +/* We just include SSE4.1 header file. */ +#include + +#endif /* _NMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/numbers b/template/sysroot/include/numbers new file mode 100644 index 0000000..9836afa --- /dev/null +++ b/template/sysroot/include/numbers @@ -0,0 +1,236 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/numbers + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMBERS +#define _GLIBCXX_NUMBERS 1 + +#pragma GCC system_header + +#define __glibcxx_want_math_constants +#include + +#ifdef __cpp_lib_math_constants // C++ >= 20 + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @defgroup math_constants Mathematical constants + * @ingroup numerics + * @{ + */ + +/// Namespace for mathematical constants +namespace numbers +{ + + /// @cond undocumented + template + using _Enable_if_floating = enable_if_t, _Tp>; + /// @endcond + + /// e + template + inline constexpr _Tp e_v + = _Enable_if_floating<_Tp>(2.718281828459045235360287471352662498L); + + /// log_2 e + template + inline constexpr _Tp log2e_v + = _Enable_if_floating<_Tp>(1.442695040888963407359924681001892137L); + + /// log_10 e + template + inline constexpr _Tp log10e_v + = _Enable_if_floating<_Tp>(0.434294481903251827651128918916605082L); + + /// pi + template + inline constexpr _Tp pi_v + = _Enable_if_floating<_Tp>(3.141592653589793238462643383279502884L); + + /// 1/pi + template + inline constexpr _Tp inv_pi_v + = _Enable_if_floating<_Tp>(0.318309886183790671537767526745028724L); + + /// 1/sqrt(pi) + template + inline constexpr _Tp inv_sqrtpi_v + = _Enable_if_floating<_Tp>(0.564189583547756286948079451560772586L); + + /// log_e 2 + template + inline constexpr _Tp ln2_v + = _Enable_if_floating<_Tp>(0.693147180559945309417232121458176568L); + + /// log_e 10 + template + inline constexpr _Tp ln10_v + = _Enable_if_floating<_Tp>(2.302585092994045684017991454684364208L); + + /// sqrt(2) + template + inline constexpr _Tp sqrt2_v + = _Enable_if_floating<_Tp>(1.414213562373095048801688724209698079L); + + /// sqrt(3) + template + inline constexpr _Tp sqrt3_v + = _Enable_if_floating<_Tp>(1.732050807568877293527446341505872367L); + + /// 1/sqrt(3) + template + inline constexpr _Tp inv_sqrt3_v + = _Enable_if_floating<_Tp>(0.577350269189625764509148780501957456L); + + /// The Euler-Mascheroni constant + template + inline constexpr _Tp egamma_v + = _Enable_if_floating<_Tp>(0.577215664901532860606512090082402431L); + + /// The golden ratio, (1+sqrt(5))/2 + template + inline constexpr _Tp phi_v + = _Enable_if_floating<_Tp>(1.618033988749894848204586834365638118L); + + inline constexpr double e = e_v; + inline constexpr double log2e = log2e_v; + inline constexpr double log10e = log10e_v; + inline constexpr double pi = pi_v; + inline constexpr double inv_pi = inv_pi_v; + inline constexpr double inv_sqrtpi = inv_sqrtpi_v; + inline constexpr double ln2 = ln2_v; + inline constexpr double ln10 = ln10_v; + inline constexpr double sqrt2 = sqrt2_v; + inline constexpr double sqrt3 = sqrt3_v; + inline constexpr double inv_sqrt3 = inv_sqrt3_v; + inline constexpr double egamma = egamma_v; + inline constexpr double phi = phi_v; + +#define __glibcxx_numbers(TYPE, SUFFIX) \ + /* e */ \ + template<> \ + inline constexpr TYPE e_v \ + = 2.718281828459045235360287471352662498##SUFFIX; \ + \ + /* log_2 e */ \ + template<> \ + inline constexpr TYPE log2e_v \ + = 1.442695040888963407359924681001892137##SUFFIX; \ + \ + /* log_10 e */ \ + template<> \ + inline constexpr TYPE log10e_v \ + = 0.434294481903251827651128918916605082##SUFFIX; \ + \ + /* pi */ \ + template<> \ + inline constexpr TYPE pi_v \ + = 3.141592653589793238462643383279502884##SUFFIX; \ + \ + /* 1/pi */ \ + template<> \ + inline constexpr TYPE inv_pi_v \ + = 0.318309886183790671537767526745028724##SUFFIX; \ + \ + /* 1/sqrt(pi) */ \ + template<> \ + inline constexpr TYPE inv_sqrtpi_v \ + = 0.564189583547756286948079451560772586##SUFFIX; \ + \ + /* log_e 2 */ \ + template<> \ + inline constexpr TYPE ln2_v \ + = 0.693147180559945309417232121458176568##SUFFIX; \ + \ + /* log_e 10 */ \ + template<> \ + inline constexpr TYPE ln10_v \ + = 2.302585092994045684017991454684364208##SUFFIX; \ + \ + /* sqrt(2) */ \ + template<> \ + inline constexpr TYPE sqrt2_v \ + = 1.414213562373095048801688724209698079##SUFFIX; \ + \ + /* sqrt(3) */ \ + template<> \ + inline constexpr TYPE sqrt3_v \ + = 1.732050807568877293527446341505872367##SUFFIX; \ + \ + /* 1/sqrt(3) */ \ + template<> \ + inline constexpr TYPE inv_sqrt3_v \ + = 0.577350269189625764509148780501957456##SUFFIX; \ + \ + /* The Euler-Mascheroni constant */ \ + template<> \ + inline constexpr TYPE egamma_v \ + = 0.577215664901532860606512090082402431##SUFFIX; \ + \ + /* The golden ratio, (1+sqrt(5))/2 */ \ + template<> \ + inline constexpr TYPE phi_v \ + = 1.618033988749894848204586834365638118##SUFFIX + +#ifdef __STDCPP_FLOAT16_T__ +__glibcxx_numbers (_Float16, F16); +#endif + +#ifdef __STDCPP_FLOAT32_T__ +__glibcxx_numbers (_Float32, F32); +#endif + +#ifdef __STDCPP_FLOAT64_T__ +__glibcxx_numbers (_Float64, F64); +#endif + +#ifdef __STDCPP_FLOAT128_T__ +__glibcxx_numbers (_Float128, F128); +#endif + +#ifdef __STDCPP_BFLOAT128_T__ +__glibcxx_numbers (__gnu_cxx::__bfloat16_t, BF16); +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) +__glibcxx_numbers (__float128, Q); +#endif // USE_FLOAT128 + +#undef __glibcxx_numbers + +} // namespace numbers +/// @} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_math_constants +#endif // _GLIBCXX_NUMBERS diff --git a/template/sysroot/include/numeric b/template/sysroot/include/numeric new file mode 100644 index 0000000..c912db4 --- /dev/null +++ b/template/sysroot/include/numeric @@ -0,0 +1,744 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/numeric + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMERIC +#define _GLIBCXX_NUMERIC 1 + +#pragma GCC system_header + +#include +#include +#include + +#ifdef _GLIBCXX_PARALLEL +# include +#endif + +#if __cplusplus >= 201402L +# include +# include +# include +#endif + +#if __cplusplus >= 201703L +# include +#endif + +#if __cplusplus > 201703L +# include +#endif + +#define __glibcxx_want_constexpr_numeric +#define __glibcxx_want_gcd +#define __glibcxx_want_gcd_lcm +#define __glibcxx_want_interpolate +#define __glibcxx_want_lcm +#define __glibcxx_want_parallel_algorithm +#define __glibcxx_want_ranges_iota +#define __glibcxx_want_saturation_arithmetic +#include + +#ifdef __glibcxx_saturation_arithmetic // C++ >= 26 +# include +#endif + +/** + * @defgroup numerics Numerics + * + * Components for performing numeric operations. Includes support for + * complex number types, random number generation, numeric (n-at-a-time) + * arrays, generalized numeric algorithms, and mathematical special functions. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201402L +namespace __detail +{ + // Like std::abs, but supports unsigned types and returns the specified type, + // so |std::numeric_limits<_Tp>::min()| is OK if representable in _Res. + template + constexpr _Res + __abs_r(_Tp __val) + { + static_assert(sizeof(_Res) >= sizeof(_Tp), + "result type must be at least as wide as the input type"); + + if (__val >= 0) + return __val; +#ifdef _GLIBCXX_ASSERTIONS + if (!__is_constant_evaluated()) // overflow already detected in constexpr + __glibcxx_assert(__val != __gnu_cxx::__int_traits<_Res>::__min); +#endif + return -static_cast<_Res>(__val); + } + + template void __abs_r(bool) = delete; + + // GCD implementation, using Stein's algorithm + template + constexpr _Tp + __gcd(_Tp __m, _Tp __n) + { + static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); + + if (__m == 0) + return __n; + if (__n == 0) + return __m; + + const int __i = std::__countr_zero(__m); + __m >>= __i; + const int __j = std::__countr_zero(__n); + __n >>= __j; + const int __k = __i < __j ? __i : __j; // min(i, j) + + while (true) + { + if (__m > __n) + { + _Tp __tmp = __m; + __m = __n; + __n = __tmp; + } + + __n -= __m; + + if (__n == 0) + return __m << __k; + + __n >>= std::__countr_zero(__n); + } + } +} // namespace __detail +#endif // C++14 + +#ifdef __cpp_lib_gcd_lcm // C++ >= 17 + /// Greatest common divisor + template + constexpr common_type_t<_Mn, _Nn> + gcd(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, + "std::gcd arguments must be integers"); + static_assert(_Mn(2) == 2 && _Nn(2) == 2, + "std::gcd arguments must not be bool"); + using _Ct = common_type_t<_Mn, _Nn>; + const _Ct __m2 = __detail::__abs_r<_Ct>(__m); + const _Ct __n2 = __detail::__abs_r<_Ct>(__n); + return __detail::__gcd>(__m2, __n2); + } + + /// Least common multiple + template + constexpr common_type_t<_Mn, _Nn> + lcm(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, + "std::lcm arguments must be integers"); + static_assert(_Mn(2) == 2 && _Nn(2) == 2, + "std::lcm arguments must not be bool"); + using _Ct = common_type_t<_Mn, _Nn>; + const _Ct __m2 = __detail::__abs_r<_Ct>(__m); + const _Ct __n2 = __detail::__abs_r<_Ct>(__n); + if (__m2 == 0 || __n2 == 0) + return 0; + _Ct __r = __m2 / __detail::__gcd>(__m2, __n2); + + if constexpr (is_signed_v<_Ct>) + if (__is_constant_evaluated()) + return __r * __n2; // constant evaluation can detect overflow here. + + bool __overflow = __builtin_mul_overflow(__r, __n2, &__r); + __glibcxx_assert(!__overflow); + return __r; + } + +#endif // __cpp_lib_gcd_lcm + + // midpoint +#ifdef __cpp_lib_interpolate // C++ >= 20 + template + constexpr + enable_if_t<__and_v, is_same, _Tp>, + __not_>>, + _Tp> + midpoint(_Tp __a, _Tp __b) noexcept + { + if constexpr (is_integral_v<_Tp>) + { + using _Up = make_unsigned_t<_Tp>; + + int __k = 1; + _Up __m = __a; + _Up __M = __b; + if (__a > __b) + { + __k = -1; + __m = __b; + __M = __a; + } + return __a + __k * _Tp(_Up(__M - __m) / 2); + } + else // is_floating + { + constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; + constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; + const _Tp __abs_a = __a < 0 ? -__a : __a; + const _Tp __abs_b = __b < 0 ? -__b : __b; + if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] + return (__a + __b) / 2; // always correctly rounded + if (__abs_a < __lo) // not safe to halve __a + return __a + __b/2; + if (__abs_b < __lo) // not safe to halve __b + return __a/2 + __b; + return __a/2 + __b/2; // otherwise correctly rounded + } + } + + template + constexpr enable_if_t, _Tp*> + midpoint(_Tp* __a, _Tp* __b) noexcept + { + static_assert( sizeof(_Tp) != 0, "type must be complete" ); + return __a + (__b - __a) / 2; + } +#endif // __cpp_lib_interpolate + +#if __cplusplus >= 201703L + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op A binary function object. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using a binary operation. + * The initial value is `init`. The values are not necessarily processed + * in order. + * + * This algorithm is similar to `std::accumulate` but is not required to + * perform the operations in order from first to last. For operations + * that are commutative and associative the result will be the same as + * for `std::accumulate`, but for other operations (such as floating point + * arithmetic) the result can be different. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + using __ref = typename iterator_traits<_InputIterator>::reference; + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, __ref>); + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, _Tp&>); + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, __ref>); + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__first[0], __first[1]); + _Tp __v2 = __binary_op(__first[2], __first[3]); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, *__first); + return __init; + } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition. + * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init) + { return std::reduce(__first, __last, std::move(__init), plus<>()); } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition, with + * an initial value of `T{}`, where `T` is the iterator's value type. + * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::value_type + reduce(_InputIterator __first, _InputIterator __last) + { + using value_type = typename iterator_traits<_InputIterator>::value_type; + return std::reduce(__first, __last, value_type{}, plus<>()); + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @param __binary_op1 The function used to perform reduction. + * @param __binary_op2 The function used to combine values from the ranges. + * @return The final sum. + * + * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` + * and then use `binary_op1` to reduce the values returned by `binary_op2` + * to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, + __is_random_access_iter<_InputIterator2>>) + { + while ((__last1 - __first1) >= 4) + { + _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), + __binary_op2(__first1[1], __first2[1])); + _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), + __binary_op2(__first1[3], __first2[3])); + _Tp __v3 = __binary_op1(__v1, __v2); + __init = __binary_op1(__init, __v3); + __first1 += 4; + __first2 += 4; + } + } + for (; __first1 != __last1; ++__first1, (void) ++__first2) + __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then + * use addition to sum those products to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + return std::transform_reduce(__first1, __last1, __first2, + std::move(__init), + plus<>(), multiplies<>()); + } + + /** + * @brief Transform the elements of a range and reduce + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op The function used to perform reduction. + * @param __unary_op The function used to transform values from the range. + * @return The final sum. + * + * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then + * use `binary_op` to reduce the values returned by `unary_op` + * to a single value of type `T`. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op, _UnaryOperation __unary_op) + { + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__unary_op(__first[0]), + __unary_op(__first[1])); + _Tp __v2 = __binary_op(__unary_op(__first[2]), + __unary_op(__first[3])); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, __unary_op(*__first)); + return __init; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, *__first); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `std::plus<>` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init) + { + return std::exclusive_scan(__first, __last, __result, std::move(__init), + plus<>()); + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, *__first); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + if (__first != __last) + { + auto __init = *__first; + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::inclusive_scan(__first, __last, __result, + __binary_op, std::move(__init)); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `std::plus<>` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { return std::inclusive_scan(__first, __last, __result, plus<>()); } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, __unary_op(*__first)); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, __unary_op(*__first)); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + if (__first != __last) + { + auto __init = __unary_op(*__first); + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::transform_inclusive_scan(__first, __last, __result, + __binary_op, __unary_op, + std::move(__init)); + } + return __result; + } + + /// @} group numeric_ops +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#if __cplusplus >= 201703L && _GLIBCXX_HOSTED +// Parallel STL algorithms +# if _PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +# include +# else +// Otherwise just pull in forward declarations +# include +# define _PSTL_NUMERIC_FORWARD_DECLARED 1 +# endif +#endif // C++17 + +#endif /* _GLIBCXX_NUMERIC */ diff --git a/template/sysroot/include/optional b/template/sysroot/include/optional new file mode 100644 index 0000000..3507c36 --- /dev/null +++ b/template/sysroot/include/optional @@ -0,0 +1,1522 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/optional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_OPTIONAL +#define _GLIBCXX_OPTIONAL 1 + +#pragma GCC system_header + +#define __glibcxx_want_freestanding_optional +#define __glibcxx_want_optional +#include + +#ifdef __cpp_lib_optional // C++ >= 17 + +#include +#include +#include +#include +#include +#include +#include +#include // _Construct +#include // in_place_t +#if __cplusplus > 201703L +# include +# include // std::__invoke +#endif +#if __cplusplus > 202002L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + template + class optional; + + /// Tag type to disengage optional objects. + struct nullopt_t + { + // Do not user-declare default constructor at all for + // optional_value = {} syntax to work. + // nullopt_t() = delete; + + // Used for constructing nullopt. + enum class _Construct { _Token }; + + // Must be constexpr for nullopt_t to be literal. + explicit constexpr nullopt_t(_Construct) noexcept { } + }; + + /// Tag to disengage optional objects. + inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; + + template struct _Optional_func { _Fn& _M_f; }; + + /** + * @brief Exception class thrown when a disengaged optional object is + * dereferenced. + * @ingroup exceptions + */ + class bad_optional_access : public exception + { + public: + bad_optional_access() = default; + virtual ~bad_optional_access() = default; + + const char* what() const noexcept override + { return "bad optional access"; } + }; + + // XXX Does not belong here. + [[__noreturn__]] inline void + __throw_bad_optional_access() + { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); } + + // This class template manages construction/destruction of + // the contained value for a std::optional. + template + struct _Optional_payload_base + { + using _Stored_type = remove_const_t<_Tp>; + + _Optional_payload_base() = default; + ~_Optional_payload_base() = default; + + template + constexpr + _Optional_payload_base(in_place_t __tag, _Args&&... __args) + : _M_payload(__tag, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + template + constexpr + _Optional_payload_base(std::initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(__il, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + // Constructor used by _Optional_base copy constructor when the + // contained value is not trivially copy constructible. + constexpr + _Optional_payload_base(bool /* __engaged */, + const _Optional_payload_base& __other) + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + } + + // Constructor used by _Optional_base move constructor when the + // contained value is not trivially move constructible. + constexpr + _Optional_payload_base(bool /* __engaged */, + _Optional_payload_base&& __other) + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + } + + // Copy constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(const _Optional_payload_base&) = default; + + // Move constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(_Optional_payload_base&&) = default; + + _Optional_payload_base& + operator=(const _Optional_payload_base&) = default; + + _Optional_payload_base& + operator=(_Optional_payload_base&&) = default; + + // used to perform non-trivial copy assignment. + constexpr void + _M_copy_assign(const _Optional_payload_base& __other) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = __other._M_get(); + else + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + else + this->_M_reset(); + } + } + + // used to perform non-trivial move assignment. + constexpr void + _M_move_assign(_Optional_payload_base&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = std::move(__other._M_get()); + else + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + else + this->_M_reset(); + } + } + + struct _Empty_byte { }; + + template> + union _Storage + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + +#if __cplusplus >= 202002L + template + constexpr + _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) + : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), + std::forward<_Arg>(__arg))) + { } +#endif + + _Empty_byte _M_empty; + _Up _M_value; + }; + + template + union _Storage<_Up, false> + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + +#if __cplusplus >= 202002L + template + constexpr + _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) + : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), + std::forward<_Arg>(__arg))) + { } +#endif + + // User-provided destructor is needed when _Up has non-trivial dtor. + _GLIBCXX20_CONSTEXPR ~_Storage() { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + _Storage<_Stored_type> _M_payload; + + bool _M_engaged = false; + + template + constexpr void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + std::_Construct(std::__addressof(this->_M_payload._M_value), + std::forward<_Args>(__args)...); + this->_M_engaged = true; + } + + constexpr void + _M_destroy() noexcept + { + _M_engaged = false; + _M_payload._M_value.~_Stored_type(); + } + +#if __cplusplus >= 202002L + template + constexpr void + _M_apply(_Optional_func<_Fn> __f, _Up&& __x) + { + std::construct_at(std::__addressof(this->_M_payload), + __f, std::forward<_Up>(__x)); + _M_engaged = true; + } +#endif + + // The _M_get() operations have _M_engaged as a precondition. + // They exist to access the contained value with the appropriate + // const-qualification, because _M_payload has had the const removed. + + constexpr _Tp& + _M_get() noexcept + { return this->_M_payload._M_value; } + + constexpr const _Tp& + _M_get() const noexcept + { return this->_M_payload._M_value; } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { + if (this->_M_engaged) + _M_destroy(); + else // This seems redundant but improves codegen, see PR 112480. + this->_M_engaged = false; + } + }; + + // Class template that manages the payload for optionals. + template , + bool /*_HasTrivialCopy */ = + is_trivially_copy_assignable_v<_Tp> + && is_trivially_copy_constructible_v<_Tp>, + bool /*_HasTrivialMove */ = + is_trivially_move_assignable_v<_Tp> + && is_trivially_move_constructible_v<_Tp>> + struct _Optional_payload; + + // Payload for potentially-constexpr optionals (trivial copy/move/destroy). + template + struct _Optional_payload<_Tp, true, true, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + }; + + // Payload for optionals with non-trivial copy construction/assignment. + template + struct _Optional_payload<_Tp, true, false, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + }; + + // Payload for optionals with non-trivial move construction/assignment. + template + struct _Optional_payload<_Tp, true, true, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial copy and move assignment. + template + struct _Optional_payload<_Tp, true, false, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial destructors. + template + struct _Optional_payload<_Tp, false, _Copy, _Move> + : _Optional_payload<_Tp, true, false, false> + { + // Base class implements all the constructors and assignment operators: + using _Optional_payload<_Tp, true, false, false>::_Optional_payload; + _Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Destructor needs to destroy the contained value: + _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); } + }; + + // Common base class for _Optional_base to avoid repeating these + // member functions in each specialization. + template + class _Optional_base_impl + { + protected: + using _Stored_type = remove_const_t<_Tp>; + + // The _M_construct operation has !_M_engaged as a precondition + // while _M_destruct has _M_engaged as a precondition. + template + constexpr void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + static_cast<_Dp*>(this)->_M_payload._M_construct( + std::forward<_Args>(__args)...); + } + + constexpr void + _M_destruct() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_reset(); } + + constexpr bool _M_is_engaged() const noexcept + { return static_cast(this)->_M_payload._M_engaged; } + + // The _M_get operations have _M_engaged as a precondition. + constexpr _Tp& + _M_get() noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast<_Dp*>(this)->_M_payload._M_get(); + } + + constexpr const _Tp& + _M_get() const noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast(this)->_M_payload._M_get(); + } + }; + + /** + * @brief Class template that provides copy/move constructors of optional. + * + * Such a separate base class template is necessary in order to + * conditionally make copy/move constructors trivial. + * + * When the contained value is trivially copy/move constructible, + * the copy/move constructors of _Optional_base will invoke the + * trivial copy/move constructor of _Optional_payload. Otherwise, + * they will invoke _Optional_payload(bool, const _Optional_payload&) + * or _Optional_payload(bool, _Optional_payload&&) to initialize + * the contained value, if copying/moving an engaged optional. + * + * Whether the other special members are trivial is determined by the + * _Optional_payload<_Tp> specialization used for the _M_payload member. + * + * @see optional, _Enable_special_members + */ + template, + bool = is_trivially_move_constructible_v<_Tp>> + struct _Optional_base + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template&, + _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr + _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, __other._M_payload) + { } + + constexpr + _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, false, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template&, + _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args... __args) + : _M_payload(in_place, __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, __other._M_payload) + { } + + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, false> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template&, + _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + + constexpr + _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template&, + _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + class optional; + + template + inline constexpr bool __is_optional_v = false; + template + inline constexpr bool __is_optional_v> = true; + + template + using __converts_from_optional = + __or_&>, + is_constructible<_Tp, optional<_Up>&>, + is_constructible<_Tp, const optional<_Up>&&>, + is_constructible<_Tp, optional<_Up>&&>, + is_convertible&, _Tp>, + is_convertible&, _Tp>, + is_convertible&&, _Tp>, + is_convertible&&, _Tp>>; + + template + using __assigns_from_optional = + __or_&>, + is_assignable<_Tp&, optional<_Up>&>, + is_assignable<_Tp&, const optional<_Up>&&>, + is_assignable<_Tp&, optional<_Up>&&>>; + + /** + * @brief Class template for optional values. + */ + template + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible_v<_Tp>, + // Copy assignment. + __and_v, is_copy_assignable<_Tp>>, + // Move constructor. + is_move_constructible_v<_Tp>, + // Move assignment. + __and_v, is_move_assignable<_Tp>>, + // Unique tag type. + optional<_Tp>> + { + static_assert(!is_same_v, nullopt_t>); + static_assert(!is_same_v, in_place_t>); + static_assert(is_object_v<_Tp> && !is_array_v<_Tp>); + + private: + using _Base = _Optional_base<_Tp>; + + // SFINAE helpers + template + using __not_self = __not_>>; + template + using __not_tag = __not_>>; + template + using _Requires = enable_if_t<__and_v<_Cond...>, bool>; + + public: + using value_type = _Tp; + + constexpr optional() noexcept { } + + constexpr optional(nullopt_t) noexcept { } + + // Converting constructors for engaged optionals. + template, __not_tag<_Up>, + is_constructible<_Tp, _Up>, + is_convertible<_Up, _Tp>> = true> + constexpr + optional(_Up&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template, __not_tag<_Up>, + is_constructible<_Tp, _Up>, + __not_>> = false> + explicit constexpr + optional(_Up&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template>, + is_constructible<_Tp, const _Up&>, + is_convertible, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(const optional<_Up>& __t) + noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) + { + if (__t) + emplace(*__t); + } + + template>, + is_constructible<_Tp, const _Up&>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(const optional<_Up>& __t) + noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) + { + if (__t) + emplace(*__t); + } + + template>, + is_constructible<_Tp, _Up>, + is_convertible<_Up, _Tp>, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(optional<_Up>&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + { + if (__t) + emplace(std::move(*__t)); + } + + template>, + is_constructible<_Tp, _Up>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(optional<_Up>&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + { + if (__t) + emplace(std::move(*__t)); + } + + template> = false> + explicit constexpr + optional(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : _Base(std::in_place, std::forward<_Args>(__args)...) { } + + template&, + _Args...>> = false> + explicit constexpr + optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, + _Args...>) + : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } + + + // Assignment operators. + _GLIBCXX20_CONSTEXPR optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_self<_Up>, + __not_<__and_, + is_same<_Tp, decay_t<_Up>>>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>, + optional&> + operator=(_Up&& __u) + noexcept(__and_v, + is_nothrow_assignable<_Tp&, _Up>>) + { + if (this->_M_is_engaged()) + this->_M_get() = std::forward<_Up>(__u); + else + this->_M_construct(std::forward<_Up>(__u)); + + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, const _Up&>, + is_assignable<_Tp&, const _Up&>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(const optional<_Up>& __u) + noexcept(__and_v, + is_nothrow_assignable<_Tp&, const _Up&>>) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = *__u; + else + this->_M_construct(*__u); + } + else + { + this->_M_reset(); + } + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(optional<_Up>&& __u) + noexcept(__and_v, + is_nothrow_assignable<_Tp&, _Up>>) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::move(*__u); + else + this->_M_construct(std::move(*__u)); + } + else + { + this->_M_reset(); + } + + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t, _Tp&> + emplace(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + { + this->_M_reset(); + this->_M_construct(std::forward<_Args>(__args)...); + return this->_M_get(); + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t&, _Args...>, + _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, + _Args...>) + { + this->_M_reset(); + this->_M_construct(__il, std::forward<_Args>(__args)...); + return this->_M_get(); + } + + // Destructor is implicit, implemented in _Optional_base. + + // Swap. + _GLIBCXX20_CONSTEXPR void + swap(optional& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> + && is_nothrow_swappable_v<_Tp>) + { + using std::swap; + + if (this->_M_is_engaged() && __other._M_is_engaged()) + swap(this->_M_get(), __other._M_get()); + else if (this->_M_is_engaged()) + { + __other._M_construct(std::move(this->_M_get())); + this->_M_destruct(); + } + else if (__other._M_is_engaged()) + { + this->_M_construct(std::move(__other._M_get())); + __other._M_destruct(); + } + } + + // Observers. + constexpr const _Tp* + operator->() const noexcept + { return std::__addressof(this->_M_get()); } + + constexpr _Tp* + operator->() noexcept + { return std::__addressof(this->_M_get()); } + + constexpr const _Tp& + operator*() const& noexcept + { return this->_M_get(); } + + constexpr _Tp& + operator*()& noexcept + { return this->_M_get(); } + + constexpr _Tp&& + operator*()&& noexcept + { return std::move(this->_M_get()); } + + constexpr const _Tp&& + operator*() const&& noexcept + { return std::move(this->_M_get()); } + + constexpr explicit operator bool() const noexcept + { return this->_M_is_engaged(); } + + constexpr bool has_value() const noexcept + { return this->_M_is_engaged(); } + + constexpr const _Tp& + value() const& + { + if (this->_M_is_engaged()) + return this->_M_get(); + __throw_bad_optional_access(); + } + + constexpr _Tp& + value()& + { + if (this->_M_is_engaged()) + return this->_M_get(); + __throw_bad_optional_access(); + } + + constexpr _Tp&& + value()&& + { + if (this->_M_is_engaged()) + return std::move(this->_M_get()); + __throw_bad_optional_access(); + } + + constexpr const _Tp&& + value() const&& + { + if (this->_M_is_engaged()) + return std::move(this->_M_get()); + __throw_bad_optional_access(); + } + + template + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(is_copy_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + if (this->_M_is_engaged()) + return this->_M_get(); + else + return static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template + constexpr _Tp + value_or(_Up&& __u) && + { + static_assert(is_move_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + if (this->_M_is_engaged()) + return std::move(this->_M_get()); + else + return static_cast<_Tp>(std::forward<_Up>(__u)); + } + +#if __cpp_lib_optional >= 202110L + // [optional.monadic] + + template + constexpr auto + and_then(_Fn&& __f) & + { + using _Up = remove_cvref_t>; + static_assert(__is_optional_v>, + "the function passed to std::optional::and_then " + "must return a std::optional"); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template + constexpr auto + and_then(_Fn&& __f) const & + { + using _Up = remove_cvref_t>; + static_assert(__is_optional_v<_Up>, + "the function passed to std::optional::and_then " + "must return a std::optional"); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template + constexpr auto + and_then(_Fn&& __f) && + { + using _Up = remove_cvref_t>; + static_assert(__is_optional_v>, + "the function passed to std::optional::and_then " + "must return a std::optional"); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template + constexpr auto + and_then(_Fn&& __f) const && + { + using _Up = remove_cvref_t>; + static_assert(__is_optional_v>, + "the function passed to std::optional::and_then " + "must return a std::optional"); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template + constexpr auto + transform(_Fn&& __f) & + { + using _Up = remove_cv_t>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template + constexpr auto + transform(_Fn&& __f) const & + { + using _Up = remove_cv_t>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template + constexpr auto + transform(_Fn&& __f) && + { + using _Up = remove_cv_t>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template + constexpr auto + transform(_Fn&& __f) const && + { + using _Up = remove_cv_t>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template requires invocable<_Fn> && copy_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) const& + { + using _Up = invoke_result_t<_Fn>; + static_assert(is_same_v, optional>, + "the function passed to std::optional::or_else " + "must return a std::optional"); + + if (has_value()) + return *this; + else + return std::forward<_Fn>(__f)(); + } + + template requires invocable<_Fn> && move_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) && + { + using _Up = invoke_result_t<_Fn>; + static_assert(is_same_v, optional>, + "the function passed to std::optional::or_else " + "must return a std::optional"); + + if (has_value()) + return std::move(*this); + else + return std::forward<_Fn>(__f)(); + } +#endif + + _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); } + + private: +#if __cplusplus >= 202002L + template friend class optional; + + template + explicit constexpr + optional(_Optional_func<_Fn> __f, _Value&& __v) + { + this->_M_payload._M_apply(__f, std::forward<_Value>(__v)); + } +#endif + }; + + template + using __optional_relop_t = + enable_if_t::value, bool>; + + template + using __optional_eq_t = __optional_relop_t< + decltype(std::declval() == std::declval()) + >; + + template + using __optional_ne_t = __optional_relop_t< + decltype(std::declval() != std::declval()) + >; + + template + using __optional_lt_t = __optional_relop_t< + decltype(std::declval() < std::declval()) + >; + + template + using __optional_gt_t = __optional_relop_t< + decltype(std::declval() > std::declval()) + >; + + template + using __optional_le_t = __optional_relop_t< + decltype(std::declval() <= std::declval()) + >; + + template + using __optional_ge_t = __optional_relop_t< + decltype(std::declval() >= std::declval()) + >; + + // Comparisons between optional values. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_eq_t<_Tp, _Up> + { + return static_cast(__lhs) == static_cast(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_ne_t<_Tp, _Up> + { + return static_cast(__lhs) != static_cast(__rhs) + || (static_cast(__lhs) && *__lhs != *__rhs); + } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_lt_t<_Tp, _Up> + { + return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_gt_t<_Tp, _Up> + { + return static_cast(__lhs) && (!__rhs || *__lhs > *__rhs); + } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_le_t<_Tp, _Up> + { + return !__lhs || (static_cast(__rhs) && *__lhs <= *__rhs); + } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_ge_t<_Tp, _Up> + { + return !__rhs || (static_cast(__lhs) && *__lhs >= *__rhs); + } + +#ifdef __cpp_lib_three_way_comparison + template _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) + { + return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); + } +#endif + + // Comparisons with nullopt. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + +#ifdef __cpp_lib_three_way_comparison + template + constexpr strong_ordering + operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept + { return bool(__x) <=> false; } +#else + template + constexpr bool + operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return false; } + + template + constexpr bool + operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return false; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template + constexpr bool + operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return true; } + + template + constexpr bool + operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return true; } + + template + constexpr bool + operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } +#endif // three-way-comparison + + // Comparisons with value type. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_eq_t<_Tp, _Up> + { return __lhs && *__lhs == __rhs; } + + template + constexpr auto + operator==(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_eq_t<_Up, _Tp> + { return __rhs && __lhs == *__rhs; } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_ne_t<_Tp, _Up> + { return !__lhs || *__lhs != __rhs; } + + template + constexpr auto + operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_ne_t<_Up, _Tp> + { return !__rhs || __lhs != *__rhs; } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_lt_t<_Tp, _Up> + { return !__lhs || *__lhs < __rhs; } + + template + constexpr auto + operator<(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_lt_t<_Up, _Tp> + { return __rhs && __lhs < *__rhs; } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_gt_t<_Tp, _Up> + { return __lhs && *__lhs > __rhs; } + + template + constexpr auto + operator>(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_gt_t<_Up, _Tp> + { return !__rhs || __lhs > *__rhs; } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_le_t<_Tp, _Up> + { return !__lhs || *__lhs <= __rhs; } + + template + constexpr auto + operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_le_t<_Up, _Tp> + { return __rhs && __lhs <= *__rhs; } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_ge_t<_Tp, _Up> + { return __lhs && *__lhs >= __rhs; } + + template + constexpr auto + operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_ge_t<_Up, _Tp> + { return !__rhs || __lhs >= *__rhs; } + +#ifdef __cpp_lib_three_way_comparison + template + requires (!__is_optional_v<_Up>) + && three_way_comparable_with<_Up, _Tp> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const _Up& __v) + { return bool(__x) ? *__x <=> __v : strong_ordering::less; } +#endif + + // Swap and creation functions. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2748. swappable traits for optionals + template + _GLIBCXX20_CONSTEXPR + inline enable_if_t && is_swappable_v<_Tp>> + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && is_swappable_v<_Tp>)> + swap(optional<_Tp>&, optional<_Tp>&) = delete; + + template + constexpr + enable_if_t, _Tp>, + optional>> + make_optional(_Tp&& __t) + noexcept(is_nothrow_constructible_v>, _Tp>) + { return optional>{ std::forward<_Tp>(__t) }; } + + template + constexpr + enable_if_t, + optional<_Tp>> + make_optional(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; } + + template + constexpr + enable_if_t&, _Args...>, + optional<_Tp>> + make_optional(initializer_list<_Up> __il, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) + { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; } + + // Hash. + + template, + bool = __poison_hash<_Up>::__enable_hash_call> + struct __optional_hash_call_base + { + size_t + operator()(const optional<_Tp>& __t) const + noexcept(noexcept(hash<_Up>{}(*__t))) + { + // We pick an arbitrary hash for disengaged optionals which hopefully + // usual values of _Tp won't typically hash to. + constexpr size_t __magic_disengaged_hash = static_cast(-3333); + return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; + } + }; + + template + struct __optional_hash_call_base<_Tp, _Up, false> {}; + + template + struct hash> + : private __poison_hash>, + public __optional_hash_call_base<_Tp> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = optional<_Tp>; + }; + + template + struct __is_fast_hash>> : __is_fast_hash> + { }; + + /// @} + +#if __cpp_deduction_guides >= 201606 + template optional(_Tp) -> optional<_Tp>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_optional + +#endif // _GLIBCXX_OPTIONAL diff --git a/template/sysroot/include/pconfigintrin.h b/template/sysroot/include/pconfigintrin.h new file mode 100644 index 0000000..e68f43c --- /dev/null +++ b/template/sysroot/include/pconfigintrin.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _PCONFIGINTRIN_H_INCLUDED +#define _PCONFIGINTRIN_H_INCLUDED + +#ifndef __PCONFIG__ +#pragma GCC push_options +#pragma GCC target("pconfig") +#define __DISABLE_PCONFIG__ +#endif /* __PCONFIG__ */ + +#define __pconfig_b(leaf, b, retval) \ + __asm__ __volatile__ ("pconfig\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b) \ + : "cc") + +#define __pconfig_generic(leaf, b, c, d, retval) \ + __asm__ __volatile__ ("pconfig\n\t" \ + : "=a" (retval), "=b" (b), "=c" (c), "=d" (d) \ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_pconfig_u32 (const unsigned int __L, size_t __D[]) +{ + enum __pconfig_type + { + __PCONFIG_KEY_PROGRAM = 0x01, + }; + + unsigned int __R = 0; + + if (!__builtin_constant_p (__L)) + __pconfig_generic (__L, __D[0], __D[1], __D[2], __R); + else switch (__L) + { + case __PCONFIG_KEY_PROGRAM: + __pconfig_b (__L, __D[0], __R); + break; + default: + __pconfig_generic (__L, __D[0], __D[1], __D[2], __R); + } + return __R; +} + +#ifdef __DISABLE_PCONFIG__ +#undef __DISABLE_PCONFIG__ +#pragma GCC pop_options +#endif /* __DISABLE_PCONFIG__ */ + +#endif /* _PCONFIGINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/pkuintrin.h b/template/sysroot/include/pkuintrin.h new file mode 100644 index 0000000..a20f1da --- /dev/null +++ b/template/sysroot/include/pkuintrin.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2015-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _PKUINTRIN_H_INCLUDED +#define _PKUINTRIN_H_INCLUDED + +#ifndef __PKU__ +#pragma GCC push_options +#pragma GCC target("pku") +#define __DISABLE_PKU__ +#endif /* __PKU__ */ + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdpkru_u32 (void) +{ + return __builtin_ia32_rdpkru (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wrpkru (unsigned int __key) +{ + __builtin_ia32_wrpkru (__key); +} + +#ifdef __DISABLE_PKU__ +#undef __DISABLE_PKU__ +#pragma GCC pop_options +#endif /* __DISABLE_PKU__ */ + +#endif /* _PKUINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/pmmintrin.h b/template/sysroot/include/pmmintrin.h new file mode 100644 index 0000000..3387861 --- /dev/null +++ b/template/sysroot/include/pmmintrin.h @@ -0,0 +1,121 @@ +/* Copyright (C) 2003-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 9.0. */ + +#ifndef _PMMINTRIN_H_INCLUDED +#define _PMMINTRIN_H_INCLUDED + +/* We need definitions from the SSE2 and SSE header files*/ +#include +#include + +#ifndef __SSE3__ +#pragma GCC push_options +#pragma GCC target("sse3") +#define __DISABLE_SSE3__ +#endif /* __SSE3__ */ + +/* Additional bits in the MXCSR. */ +#define _MM_DENORMALS_ZERO_MASK 0x0040 +#define _MM_DENORMALS_ZERO_ON 0x0040 +#define _MM_DENORMALS_ZERO_OFF 0x0000 + +#define _MM_SET_DENORMALS_ZERO_MODE(mode) \ + _mm_setcsr ((_mm_getcsr () & ~_MM_DENORMALS_ZERO_MASK) | (mode)) +#define _MM_GET_DENORMALS_ZERO_MODE() \ + (_mm_getcsr() & _MM_DENORMALS_ZERO_MASK) + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_addsub_ps (__m128 __X, __m128 __Y) +{ + return (__m128) __builtin_ia32_addsubps ((__v4sf)__X, (__v4sf)__Y); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_ps (__m128 __X, __m128 __Y) +{ + return (__m128) __builtin_ia32_haddps ((__v4sf)__X, (__v4sf)__Y); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_ps (__m128 __X, __m128 __Y) +{ + return (__m128) __builtin_ia32_hsubps ((__v4sf)__X, (__v4sf)__Y); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movehdup_ps (__m128 __X) +{ + return (__m128) __builtin_ia32_movshdup ((__v4sf)__X); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_moveldup_ps (__m128 __X) +{ + return (__m128) __builtin_ia32_movsldup ((__v4sf)__X); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_addsub_pd (__m128d __X, __m128d __Y) +{ + return (__m128d) __builtin_ia32_addsubpd ((__v2df)__X, (__v2df)__Y); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_pd (__m128d __X, __m128d __Y) +{ + return (__m128d) __builtin_ia32_haddpd ((__v2df)__X, (__v2df)__Y); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_pd (__m128d __X, __m128d __Y) +{ + return (__m128d) __builtin_ia32_hsubpd ((__v2df)__X, (__v2df)__Y); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loaddup_pd (double const *__P) +{ + return _mm_load1_pd (__P); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movedup_pd (__m128d __X) +{ + return _mm_shuffle_pd (__X, __X, _MM_SHUFFLE2 (0,0)); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_lddqu_si128 (__m128i const *__P) +{ + return (__m128i) __builtin_ia32_lddqu ((char const *)__P); +} + +#ifdef __DISABLE_SSE3__ +#undef __DISABLE_SSE3__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE3__ */ + +#endif /* _PMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/popcntintrin.h b/template/sysroot/include/popcntintrin.h new file mode 100644 index 0000000..e7c620f --- /dev/null +++ b/template/sysroot/include/popcntintrin.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2009-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _POPCNTINTRIN_H_INCLUDED +#define _POPCNTINTRIN_H_INCLUDED + +#ifndef __POPCNT__ +#pragma GCC push_options +#pragma GCC target("popcnt") +#define __DISABLE_POPCNT__ +#endif /* __POPCNT__ */ + +/* Calculate a number of bits set to 1. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_u32 (unsigned int __X) +{ + return __builtin_popcount (__X); +} + +#ifdef __x86_64__ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_popcnt_u64 (unsigned long long __X) +{ + return __builtin_popcountll (__X); +} +#endif + +#ifdef __DISABLE_POPCNT__ +#undef __DISABLE_POPCNT__ +#pragma GCC pop_options +#endif /* __DISABLE_POPCNT__ */ + +#endif /* _POPCNTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/prfchiintrin.h b/template/sysroot/include/prfchiintrin.h new file mode 100644 index 0000000..dfca89c --- /dev/null +++ b/template/sysroot/include/prfchiintrin.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2022-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _PRFCHIINTRIN_H_INCLUDED +#define _PRFCHIINTRIN_H_INCLUDED + +#ifdef __x86_64__ + + +#ifndef __PREFETCHI__ +#pragma GCC push_options +#pragma GCC target("prefetchi") +#define __DISABLE_PREFETCHI__ +#endif /* __PREFETCHI__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_prefetchit0 (void* __P) +{ + __builtin_ia32_prefetchi (__P, 3); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_prefetchit1 (void* __P) +{ + __builtin_ia32_prefetchi (__P, 2); +} + +#ifdef __DISABLE_PREFETCHI__ +#undef __DISABLE_PREFETCHI__ +#pragma GCC pop_options +#endif /* __DISABLE_PREFETCHI__ */ + +#endif /* __x86_64__ */ + +#endif /* _PRFCHIINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/prfchwintrin.h b/template/sysroot/include/prfchwintrin.h new file mode 100644 index 0000000..b7dbebe --- /dev/null +++ b/template/sysroot/include/prfchwintrin.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _IMMINTRIN_H_INCLUDED && !defined _MM3DNOW_H_INCLUDED +# error "Never use directly; include or instead." +#endif + +#ifndef _PRFCHWINTRIN_H_INCLUDED +#define _PRFCHWINTRIN_H_INCLUDED + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_prefetchw (void *__P) +{ + __builtin_prefetch (__P, 1, 3 /* _MM_HINT_T0 */); +} + +#endif /* _PRFCHWINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/ranges b/template/sysroot/include/ranges new file mode 100644 index 0000000..afce818 --- /dev/null +++ b/template/sysroot/include/ranges @@ -0,0 +1,9521 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ranges + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_RANGES +#define _GLIBCXX_RANGES 1 + +#if __cplusplus > 201703L + +#pragma GCC system_header + +#include + +#if __cpp_lib_concepts + +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 202002L +#include +#endif +#include +#include + +#define __glibcxx_want_ranges +#define __glibcxx_want_ranges_as_const +#define __glibcxx_want_ranges_as_rvalue +#define __glibcxx_want_ranges_cartesian_product +#define __glibcxx_want_ranges_chunk +#define __glibcxx_want_ranges_chunk_by +#define __glibcxx_want_ranges_enumerate +#define __glibcxx_want_ranges_iota +#define __glibcxx_want_ranges_join_with +#define __glibcxx_want_ranges_repeat +#define __glibcxx_want_ranges_slide +#define __glibcxx_want_ranges_stride +#define __glibcxx_want_ranges_to_container +#define __glibcxx_want_ranges_zip +#include + +#ifdef __glibcxx_generator // C++ >= 23 && __glibcxx_coroutine +# include +#endif + +/** + * @defgroup ranges Ranges + * + * Components for dealing with ranges of elements. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + // [range.access] customization point objects + // [range.req] range and view concepts + // [range.dangling] dangling iterator handling + // Defined in + + // [view.interface] View interface + // [range.subrange] Sub-ranges + // Defined in + + // C++20 24.6 [range.factories] Range factories + + /// A view that contains no elements. + template requires is_object_v<_Tp> + class empty_view + : public view_interface> + { + public: + static constexpr _Tp* begin() noexcept { return nullptr; } + static constexpr _Tp* end() noexcept { return nullptr; } + static constexpr _Tp* data() noexcept { return nullptr; } + static constexpr size_t size() noexcept { return 0; } + static constexpr bool empty() noexcept { return true; } + }; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace __detail + { +#if __cpp_lib_ranges >= 202207L // C++ >= 23 + // P2494R2 Relaxing range adaptors to allow for move only types + template + concept __boxable = move_constructible<_Tp> && is_object_v<_Tp>; +#else + template + concept __boxable = copy_constructible<_Tp> && is_object_v<_Tp>; +#endif + + template<__boxable _Tp> + struct __box : std::optional<_Tp> + { + using std::optional<_Tp>::optional; + + constexpr + __box() + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : std::optional<_Tp>{std::in_place} + { } + + __box(const __box&) = default; + __box(__box&&) = default; + + using std::optional<_Tp>::operator=; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3477. Simplify constraints for semiregular-box + // 3572. copyable-box should be fully constexpr + constexpr __box& + operator=(const __box& __that) + noexcept(is_nothrow_copy_constructible_v<_Tp>) + requires (!copyable<_Tp>) && copy_constructible<_Tp> + { + if (this != std::__addressof(__that)) + { + if ((bool)__that) + this->emplace(*__that); + else + this->reset(); + } + return *this; + } + + constexpr __box& + operator=(__box&& __that) + noexcept(is_nothrow_move_constructible_v<_Tp>) + requires (!movable<_Tp>) + { + if (this != std::__addressof(__that)) + { + if ((bool)__that) + this->emplace(std::move(*__that)); + else + this->reset(); + } + return *this; + } + }; + + template + concept __boxable_copyable + = copy_constructible<_Tp> + && (copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> + && is_nothrow_copy_constructible_v<_Tp>)); + template + concept __boxable_movable + = (!copy_constructible<_Tp>) + && (movable<_Tp> || is_nothrow_move_constructible_v<_Tp>); + + // For types which are already copyable (or since C++23, movable) + // this specialization of the box wrapper stores the object directly + // without going through std::optional. It provides just the subset of + // the primary template's API that we currently use. + template<__boxable _Tp> + requires __boxable_copyable<_Tp> || __boxable_movable<_Tp> + struct __box<_Tp> + { + private: + [[no_unique_address]] _Tp _M_value = _Tp(); + + public: + __box() requires default_initializable<_Tp> = default; + + constexpr explicit + __box(const _Tp& __t) + noexcept(is_nothrow_copy_constructible_v<_Tp>) + requires copy_constructible<_Tp> + : _M_value(__t) + { } + + constexpr explicit + __box(_Tp&& __t) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_value(std::move(__t)) + { } + + template + requires constructible_from<_Tp, _Args...> + constexpr explicit + __box(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : _M_value(std::forward<_Args>(__args)...) + { } + + __box(const __box&) = default; + __box(__box&&) = default; + __box& operator=(const __box&) requires copyable<_Tp> = default; + __box& operator=(__box&&) requires movable<_Tp> = default; + + // When _Tp is nothrow_copy_constructible but not copy_assignable, + // copy assignment is implemented via destroy-then-copy-construct. + constexpr __box& + operator=(const __box& __that) noexcept + requires (!copyable<_Tp>) && copy_constructible<_Tp> + { + static_assert(is_nothrow_copy_constructible_v<_Tp>); + if (this != std::__addressof(__that)) + { + _M_value.~_Tp(); + std::construct_at(std::__addressof(_M_value), *__that); + } + return *this; + } + + // Likewise for move assignment. + constexpr __box& + operator=(__box&& __that) noexcept + requires (!movable<_Tp>) + { + static_assert(is_nothrow_move_constructible_v<_Tp>); + if (this != std::__addressof(__that)) + { + _M_value.~_Tp(); + std::construct_at(std::__addressof(_M_value), std::move(*__that)); + } + return *this; + } + + constexpr bool + has_value() const noexcept + { return true; }; + + constexpr _Tp& + operator*() & noexcept + { return _M_value; } + + constexpr const _Tp& + operator*() const & noexcept + { return _M_value; } + + constexpr _Tp&& + operator*() && noexcept + { return std::move(_M_value); } + + constexpr const _Tp&& + operator*() const && noexcept + { return std::move(_M_value); } + + constexpr _Tp* + operator->() noexcept + { return std::__addressof(_M_value); } + + constexpr const _Tp* + operator->() const noexcept + { return std::__addressof(_M_value); } + }; + } // namespace __detail + + /// A view that contains exactly one element. +#if __cpp_lib_ranges >= 202207L // C++ >= 23 + template +#else + template +#endif + requires is_object_v<_Tp> + class single_view : public view_interface> + { + public: + single_view() requires default_initializable<_Tp> = default; + + constexpr explicit + single_view(const _Tp& __t) + noexcept(is_nothrow_copy_constructible_v<_Tp>) + requires copy_constructible<_Tp> + : _M_value(__t) + { } + + constexpr explicit + single_view(_Tp&& __t) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_value(std::move(__t)) + { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3428. single_view's in place constructor should be explicit + template + requires constructible_from<_Tp, _Args...> + constexpr explicit + single_view(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : _M_value{in_place, std::forward<_Args>(__args)...} + { } + + constexpr _Tp* + begin() noexcept + { return data(); } + + constexpr const _Tp* + begin() const noexcept + { return data(); } + + constexpr _Tp* + end() noexcept + { return data() + 1; } + + constexpr const _Tp* + end() const noexcept + { return data() + 1; } + + static constexpr size_t + size() noexcept + { return 1; } + + constexpr _Tp* + data() noexcept + { return _M_value.operator->(); } + + constexpr const _Tp* + data() const noexcept + { return _M_value.operator->(); } + + private: + [[no_unique_address]] __detail::__box<_Tp> _M_value; + }; + + template + single_view(_Tp) -> single_view<_Tp>; + + namespace __detail + { + template + constexpr auto __to_signed_like(_Wp __w) noexcept + { + if constexpr (!integral<_Wp>) + return iter_difference_t<_Wp>(); + else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) + return iter_difference_t<_Wp>(__w); + else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) + return ptrdiff_t(__w); + else if constexpr (sizeof(long long) > sizeof(_Wp)) + return (long long)(__w); +#ifdef __SIZEOF_INT128__ + else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) + return __int128(__w); +#endif + else + return __max_diff_type(__w); + } + + template + using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); + + template + concept __decrementable = incrementable<_It> + && requires(_It __i) + { + { --__i } -> same_as<_It&>; + { __i-- } -> same_as<_It>; + }; + + template + concept __advanceable = __decrementable<_It> && totally_ordered<_It> + && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n) + { + { __i += __n } -> same_as<_It&>; + { __i -= __n } -> same_as<_It&>; + _It(__j + __n); + _It(__n + __j); + _It(__j - __n); + { __j - __j } -> convertible_to<__iota_diff_t<_It>>; + }; + + template + struct __iota_view_iter_cat + { }; + + template + struct __iota_view_iter_cat<_Winc> + { using iterator_category = input_iterator_tag; }; + } // namespace __detail + + template + requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound> + && copyable<_Winc> + class iota_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator : __detail::__iota_view_iter_cat<_Winc> + { + private: + static auto + _S_iter_concept() + { + using namespace __detail; + if constexpr (__advanceable<_Winc>) + return random_access_iterator_tag{}; + else if constexpr (__decrementable<_Winc>) + return bidirectional_iterator_tag{}; + else if constexpr (incrementable<_Winc>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in __iota_view_iter_cat + using value_type = _Winc; + using difference_type = __detail::__iota_diff_t<_Winc>; + + _Iterator() requires default_initializable<_Winc> = default; + + constexpr explicit + _Iterator(_Winc __value) + : _M_value(__value) { } + + constexpr _Winc + operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>) + { return _M_value; } + + constexpr _Iterator& + operator++() + { + ++_M_value; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires incrementable<_Winc> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires __detail::__decrementable<_Winc> + { + --_M_value; + return *this; + } + + constexpr _Iterator + operator--(int) requires __detail::__decrementable<_Winc> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value += static_cast<_Winc>(__n); + else + _M_value -= static_cast<_Winc>(-__n); + } + else + _M_value += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value -= static_cast<_Winc>(__n); + else + _M_value += static_cast<_Winc>(-__n); + } + else + _M_value -= __n; + return *this; + } + + constexpr _Winc + operator[](difference_type __n) const + requires __detail::__advanceable<_Winc> + { return _Winc(_M_value + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Winc> + { return __x._M_value == __y._M_value; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __x._M_value < __y._M_value; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> && three_way_comparable<_Winc> + { return __x._M_value <=> __y._M_value; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { + __i += __n; + return __i; + } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires __detail::__advanceable<_Winc> + { return __i += __n; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { + __i -= __n; + return __i; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + using _Dt = difference_type; + if constexpr (__is_integer_like<_Winc>) + { + if constexpr (__is_signed_integer_like<_Winc>) + return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value)); + else + return (__y._M_value > __x._M_value) + ? _Dt(-_Dt(__y._M_value - __x._M_value)) + : _Dt(__x._M_value - __y._M_value); + } + else + return __x._M_value - __y._M_value; + } + + private: + _Winc _M_value = _Winc(); + + friend iota_view; + friend _Sentinel; + }; + + struct _Sentinel + { + private: + constexpr bool + _M_equal(const _Iterator& __x) const + { return __x._M_value == _M_bound; } + + constexpr auto + _M_distance_from(const _Iterator& __x) const + { return _M_bound - __x._M_value; } + + _Bound _M_bound = _Bound(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Bound __bound) + : _M_bound(__bound) { } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Iterator& __x, const _Sentinel& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return -__y._M_distance_from(__x); } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Sentinel& __x, const _Iterator& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return __x._M_distance_from(__y); } + + friend iota_view; + }; + + _Winc _M_value = _Winc(); + [[no_unique_address]] _Bound _M_bound = _Bound(); + + public: + iota_view() requires default_initializable<_Winc> = default; + + constexpr explicit + iota_view(_Winc __value) + : _M_value(__value) + { } + + constexpr + iota_view(type_identity_t<_Winc> __value, + type_identity_t<_Bound> __bound) + : _M_value(__value), _M_bound(__bound) + { + if constexpr (totally_ordered_with<_Winc, _Bound>) + __glibcxx_assert( bool(__value <= __bound) ); + } + + constexpr + iota_view(_Iterator __first, _Iterator __last) + requires same_as<_Winc, _Bound> + : iota_view(__first._M_value, __last._M_value) + { } + + constexpr + iota_view(_Iterator __first, unreachable_sentinel_t __last) + requires same_as<_Bound, unreachable_sentinel_t> + : iota_view(__first._M_value, __last) + { } + + constexpr + iota_view(_Iterator __first, _Sentinel __last) + requires (!same_as<_Winc, _Bound>) && (!same_as<_Bound, unreachable_sentinel_t>) + : iota_view(__first._M_value, __last._M_bound) + { } + + constexpr _Iterator + begin() const { return _Iterator{_M_value}; } + + constexpr auto + end() const + { + if constexpr (same_as<_Bound, unreachable_sentinel_t>) + return unreachable_sentinel; + else + return _Sentinel{_M_bound}; + } + + constexpr _Iterator + end() const requires same_as<_Winc, _Bound> + { return _Iterator{_M_bound}; } + + constexpr auto + size() const + requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) + || (integral<_Winc> && integral<_Bound>) + || sized_sentinel_for<_Bound, _Winc> + { + using __detail::__is_integer_like; + using __detail::__to_unsigned_like; + if constexpr (integral<_Winc> && integral<_Bound>) + { + using _Up = make_unsigned_t; + return _Up(_M_bound) - _Up(_M_value); + } + else if constexpr (__is_integer_like<_Winc>) + return __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value); + else + return __to_unsigned_like(_M_bound - _M_value); + } + }; + + template + requires (!__detail::__is_integer_like<_Winc> + || !__detail::__is_integer_like<_Bound> + || (__detail::__is_signed_integer_like<_Winc> + == __detail::__is_signed_integer_like<_Bound>)) + iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>; + + template + inline constexpr bool + enable_borrowed_range> = true; + +namespace views +{ + template + inline constexpr empty_view<_Tp> empty{}; + + namespace __detail + { + template + concept __can_single_view + = requires { single_view>(std::declval<_Tp>()); }; + } // namespace __detail + + struct _Single + { + template<__detail::__can_single_view _Tp> + constexpr auto + operator() [[nodiscard]] (_Tp&& __e) const + noexcept(noexcept(single_view>(std::forward<_Tp>(__e)))) + { return single_view>(std::forward<_Tp>(__e)); } + }; + + inline constexpr _Single single{}; + + namespace __detail + { + template + concept __can_iota_view = requires { iota_view(std::declval<_Args>()...); }; + } // namespace __detail + + struct _Iota + { + template<__detail::__can_iota_view _Tp> + constexpr auto + operator() [[nodiscard]] (_Tp&& __e) const + { return iota_view(std::forward<_Tp>(__e)); } + + template + requires __detail::__can_iota_view<_Tp, _Up> + constexpr auto + operator() [[nodiscard]] (_Tp&& __e, _Up&& __f) const + { return iota_view(std::forward<_Tp>(__e), std::forward<_Up>(__f)); } + }; + + inline constexpr _Iota iota{}; +} // namespace views + +#if _GLIBCXX_HOSTED + namespace __detail + { + template + concept __stream_extractable + = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; }; + } // namespace __detail + + template> + requires default_initializable<_Val> + && __detail::__stream_extractable<_Val, _CharT, _Traits> + class basic_istream_view + : public view_interface> + { + public: + constexpr explicit + basic_istream_view(basic_istream<_CharT, _Traits>& __stream) + : _M_stream(std::__addressof(__stream)) + { } + + constexpr auto + begin() + { + *_M_stream >> _M_object; + return _Iterator{this}; + } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + private: + basic_istream<_CharT, _Traits>* _M_stream; + _Val _M_object = _Val(); + + struct _Iterator + { + public: + using iterator_concept = input_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = _Val; + + constexpr explicit + _Iterator(basic_istream_view* __parent) noexcept + : _M_parent(__parent) + { } + + _Iterator(const _Iterator&) = delete; + _Iterator(_Iterator&&) = default; + _Iterator& operator=(const _Iterator&) = delete; + _Iterator& operator=(_Iterator&&) = default; + + _Iterator& + operator++() + { + *_M_parent->_M_stream >> _M_parent->_M_object; + return *this; + } + + void + operator++(int) + { ++*this; } + + _Val& + operator*() const + { return _M_parent->_M_object; } + + friend bool + operator==(const _Iterator& __x, default_sentinel_t) + { return __x._M_at_end(); } + + private: + basic_istream_view* _M_parent; + + bool + _M_at_end() const + { return !*_M_parent->_M_stream; } + }; + + friend _Iterator; + }; + + template + using istream_view = basic_istream_view<_Val, char>; + + template + using wistream_view = basic_istream_view<_Val, wchar_t>; + +namespace views +{ + namespace __detail + { + template + concept __can_istream_view = requires (_Up __e) { + basic_istream_view<_Tp, typename _Up::char_type, typename _Up::traits_type>(__e); + }; + } // namespace __detail + + template + struct _Istream + { + template + constexpr auto + operator() [[nodiscard]] (basic_istream<_CharT, _Traits>& __e) const + requires __detail::__can_istream_view<_Tp, remove_reference_t> + { return basic_istream_view<_Tp, _CharT, _Traits>(__e); } + }; + + template + inline constexpr _Istream<_Tp> istream; +} +#endif // HOSTED + + // C++20 24.7 [range.adaptors] Range adaptors + +namespace __detail +{ + template + struct _Absent { }; + + // Alias for a type that is conditionally present + // (and is an empty type otherwise). + // Data members using this alias should use [[no_unique_address]] so that + // they take no space when not needed. + // The optional template parameter _Disc is for discriminating two otherwise + // equivalent absent types so that even they can overlap. + template + using __maybe_present_t = __conditional_t<_Present, _Tp, _Absent<_Tp, _Disc>>; + + // Alias for a type that is conditionally const. + template + using __maybe_const_t = __conditional_t<_Const, const _Tp, _Tp>; + +} // namespace __detail + +// Shorthand for __detail::__maybe_const_t. +using __detail::__maybe_const_t; + +namespace views::__adaptor +{ + // True if the range adaptor _Adaptor can be applied with _Args. + template + concept __adaptor_invocable + = requires { std::declval<_Adaptor>()(declval<_Args>()...); }; + + // True if the range adaptor non-closure _Adaptor can be partially applied + // with _Args. + template + concept __adaptor_partial_app_viable = (_Adaptor::_S_arity > 1) + && (sizeof...(_Args) == _Adaptor::_S_arity - 1) + && (constructible_from, _Args> && ...); + + template + struct _Partial; + + template + struct _Pipe; + + // The base class of every range adaptor closure. + // + // The derived class should define the optional static data member + // _S_has_simple_call_op to true if the behavior of this adaptor is + // independent of the constness/value category of the adaptor object. + template + struct _RangeAdaptorClosure + { }; + + template + requires (!same_as<_Tp, _RangeAdaptorClosure<_Up>>) + void __is_range_adaptor_closure_fn + (const _Tp&, const _RangeAdaptorClosure<_Up>&); // not defined + + template + concept __is_range_adaptor_closure + = requires (_Tp __t) { __adaptor::__is_range_adaptor_closure_fn(__t, __t); }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdangling-reference" + // range | adaptor is equivalent to adaptor(range). + template + requires __is_range_adaptor_closure<_Self> + && __adaptor_invocable<_Self, _Range> + constexpr auto + operator|(_Range&& __r, _Self&& __self) + { return std::forward<_Self>(__self)(std::forward<_Range>(__r)); } + + // Compose the adaptors __lhs and __rhs into a pipeline, returning + // another range adaptor closure object. + template + requires __is_range_adaptor_closure<_Lhs> + && __is_range_adaptor_closure<_Rhs> + constexpr auto + operator|(_Lhs&& __lhs, _Rhs&& __rhs) + { + return _Pipe, decay_t<_Rhs>>{std::forward<_Lhs>(__lhs), + std::forward<_Rhs>(__rhs)}; + } +#pragma GCC diagnostic pop + + // The base class of every range adaptor non-closure. + // + // The static data member _Derived::_S_arity must contain the total number of + // arguments that the adaptor takes, and the class _Derived must introduce + // _RangeAdaptor::operator() into the class scope via a using-declaration. + // + // The optional static data member _Derived::_S_has_simple_extra_args should + // be defined to true if the behavior of this adaptor is independent of the + // constness/value category of the extra arguments. This data member could + // also be defined as a variable template parameterized by the types of the + // extra arguments. + template + struct _RangeAdaptor + { + // Partially apply the arguments __args to the range adaptor _Derived, + // returning a range adaptor closure object. + template + requires __adaptor_partial_app_viable<_Derived, _Args...> + constexpr auto + operator()(_Args&&... __args) const + { + return _Partial<_Derived, decay_t<_Args>...>{0, std::forward<_Args>(__args)...}; + } + }; + + // True if the range adaptor closure _Adaptor has a simple operator(), i.e. + // one that's not overloaded according to constness or value category of the + // _Adaptor object. + template + concept __closure_has_simple_call_op = _Adaptor::_S_has_simple_call_op; + + // True if the behavior of the range adaptor non-closure _Adaptor is + // independent of the value category of its extra arguments _Args. + template + concept __adaptor_has_simple_extra_args = _Adaptor::_S_has_simple_extra_args + || _Adaptor::template _S_has_simple_extra_args<_Args...>; + + // A range adaptor closure that represents partial application of + // the range adaptor _Adaptor with arguments _Args. + template + struct _Partial : _RangeAdaptorClosure<_Partial<_Adaptor, _Args...>> + { + tuple<_Args...> _M_args; + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template + constexpr + _Partial(int, _Ts&&... __args) + : _M_args(std::forward<_Ts>(__args)...) + { } + + // Invoke _Adaptor with arguments __r, _M_args... according to the + // value category of this _Partial object. +#if __cpp_explicit_this_parameter + template + requires __adaptor_invocable<_Adaptor, _Range, __like_t<_Self, _Args>...> + constexpr auto + operator()(this _Self&& __self, _Range&& __r) + { + auto __forwarder = [&__r] (auto&&... __args) { + return _Adaptor{}(std::forward<_Range>(__r), + std::forward(__args)...); + }; + return std::apply(__forwarder, std::forward<_Self>(__self)._M_args); + } +#else + template + requires __adaptor_invocable<_Adaptor, _Range, const _Args&...> + constexpr auto + operator()(_Range&& __r) const & + { + auto __forwarder = [&__r] (const auto&... __args) { + return _Adaptor{}(std::forward<_Range>(__r), __args...); + }; + return std::apply(__forwarder, _M_args); + } + + template + requires __adaptor_invocable<_Adaptor, _Range, _Args...> + constexpr auto + operator()(_Range&& __r) && + { + auto __forwarder = [&__r] (auto&... __args) { + return _Adaptor{}(std::forward<_Range>(__r), std::move(__args)...); + }; + return std::apply(__forwarder, _M_args); + } + + template + constexpr auto + operator()(_Range&& __r) const && = delete; +#endif + }; + + // A lightweight specialization of the above primary template for + // the common case where _Adaptor accepts a single extra argument. + template + struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure<_Partial<_Adaptor, _Arg>> + { + _Arg _M_arg; + + template + constexpr + _Partial(int, _Tp&& __arg) + : _M_arg(std::forward<_Tp>(__arg)) + { } + +#if __cpp_explicit_this_parameter + template + requires __adaptor_invocable<_Adaptor, _Range, __like_t<_Self, _Arg>> + constexpr auto + operator()(this _Self&& __self, _Range&& __r) + { return _Adaptor{}(std::forward<_Range>(__r), std::forward<_Self>(__self)._M_arg); } +#else + template + requires __adaptor_invocable<_Adaptor, _Range, const _Arg&> + constexpr auto + operator()(_Range&& __r) const & + { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); } + + template + requires __adaptor_invocable<_Adaptor, _Range, _Arg> + constexpr auto + operator()(_Range&& __r) && + { return _Adaptor{}(std::forward<_Range>(__r), std::move(_M_arg)); } + + template + constexpr auto + operator()(_Range&& __r) const && = delete; +#endif + }; + + // Partial specialization of the primary template for the case where the extra + // arguments of the adaptor can always be safely and efficiently forwarded by + // const reference. This lets us get away with a single operator() overload, + // which makes overload resolution failure diagnostics more concise. + template + requires __adaptor_has_simple_extra_args<_Adaptor, _Args...> + && (is_trivially_copyable_v<_Args> && ...) + struct _Partial<_Adaptor, _Args...> : _RangeAdaptorClosure<_Partial<_Adaptor, _Args...>> + { + tuple<_Args...> _M_args; + + template + constexpr + _Partial(int, _Ts&&... __args) + : _M_args(std::forward<_Ts>(__args)...) + { } + + // Invoke _Adaptor with arguments __r, const _M_args&... regardless + // of the value category of this _Partial object. + template + requires __adaptor_invocable<_Adaptor, _Range, const _Args&...> + constexpr auto + operator()(_Range&& __r) const + { + auto __forwarder = [&__r] (const auto&... __args) { + return _Adaptor{}(std::forward<_Range>(__r), __args...); + }; + return std::apply(__forwarder, _M_args); + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + // A lightweight specialization of the above template for the common case + // where _Adaptor accepts a single extra argument. + template + requires __adaptor_has_simple_extra_args<_Adaptor, _Arg> + && is_trivially_copyable_v<_Arg> + struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure<_Partial<_Adaptor, _Arg>> + { + _Arg _M_arg; + + template + constexpr + _Partial(int, _Tp&& __arg) + : _M_arg(std::forward<_Tp>(__arg)) + { } + + template + requires __adaptor_invocable<_Adaptor, _Range, const _Arg&> + constexpr auto + operator()(_Range&& __r) const + { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); } + + static constexpr bool _S_has_simple_call_op = true; + }; + + template + concept __pipe_invocable + = requires { std::declval<_Rhs>()(std::declval<_Lhs>()(std::declval<_Range>())); }; + + // A range adaptor closure that represents composition of the range + // adaptor closures _Lhs and _Rhs. + template + struct _Pipe : _RangeAdaptorClosure<_Pipe<_Lhs, _Rhs>> + { + [[no_unique_address]] _Lhs _M_lhs; + [[no_unique_address]] _Rhs _M_rhs; + + template + constexpr + _Pipe(_Tp&& __lhs, _Up&& __rhs) + : _M_lhs(std::forward<_Tp>(__lhs)), _M_rhs(std::forward<_Up>(__rhs)) + { } + + // Invoke _M_rhs(_M_lhs(__r)) according to the value category of this + // range adaptor closure object. +#if __cpp_explicit_this_parameter + template + requires __pipe_invocable<__like_t<_Self, _Lhs>, __like_t<_Self, _Rhs>, _Range> + constexpr auto + operator()(this _Self&& __self, _Range&& __r) + { + return (std::forward<_Self>(__self)._M_rhs + (std::forward<_Self>(__self)._M_lhs + (std::forward<_Range>(__r)))); + } +#else + template + requires __pipe_invocable + constexpr auto + operator()(_Range&& __r) const & + { return _M_rhs(_M_lhs(std::forward<_Range>(__r))); } + + template + requires __pipe_invocable<_Lhs, _Rhs, _Range> + constexpr auto + operator()(_Range&& __r) && + { return std::move(_M_rhs)(std::move(_M_lhs)(std::forward<_Range>(__r))); } + + template + constexpr auto + operator()(_Range&& __r) const && = delete; +#endif + }; + + // A partial specialization of the above primary template for the case where + // both adaptor operands have a simple operator(). This in turn lets us + // implement composition using a single simple operator(), which makes + // overload resolution failure diagnostics more concise. + template + requires __closure_has_simple_call_op<_Lhs> + && __closure_has_simple_call_op<_Rhs> + struct _Pipe<_Lhs, _Rhs> : _RangeAdaptorClosure<_Pipe<_Lhs, _Rhs>> + { + [[no_unique_address]] _Lhs _M_lhs; + [[no_unique_address]] _Rhs _M_rhs; + + template + constexpr + _Pipe(_Tp&& __lhs, _Up&& __rhs) + : _M_lhs(std::forward<_Tp>(__lhs)), _M_rhs(std::forward<_Up>(__rhs)) + { } + + template + requires __pipe_invocable + constexpr auto + operator()(_Range&& __r) const + { return _M_rhs(_M_lhs(std::forward<_Range>(__r))); } + + static constexpr bool _S_has_simple_call_op = true; + }; +} // namespace views::__adaptor + +#if __cpp_lib_ranges >= 202202L + // P2387R3 Pipe support for user-defined range adaptors + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class range_adaptor_closure + : public views::__adaptor::_RangeAdaptorClosure<_Derived> + { }; +#endif + + template requires is_object_v<_Range> + class ref_view : public view_interface> + { + private: + _Range* _M_r; + + static void _S_fun(_Range&); // not defined + static void _S_fun(_Range&&) = delete; + + public: + template<__detail::__different_from _Tp> + requires convertible_to<_Tp, _Range&> + && requires { _S_fun(declval<_Tp>()); } + constexpr + ref_view(_Tp&& __t) + noexcept(noexcept(static_cast<_Range&>(std::declval<_Tp>()))) + : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) + { } + + constexpr _Range& + base() const + { return *_M_r; } + + constexpr iterator_t<_Range> + begin() const + { return ranges::begin(*_M_r); } + + constexpr sentinel_t<_Range> + end() const + { return ranges::end(*_M_r); } + + constexpr bool + empty() const requires requires { ranges::empty(*_M_r); } + { return ranges::empty(*_M_r); } + + constexpr auto + size() const requires sized_range<_Range> + { return ranges::size(*_M_r); } + + constexpr auto + data() const requires contiguous_range<_Range> + { return ranges::data(*_M_r); } + }; + + template + ref_view(_Range&) -> ref_view<_Range>; + + template + inline constexpr bool enable_borrowed_range> = true; + + template + requires movable<_Range> + && (!__detail::__is_initializer_list>) + class owning_view : public view_interface> + { + private: + _Range _M_r = _Range(); + + public: + owning_view() requires default_initializable<_Range> = default; + + constexpr + owning_view(_Range&& __t) + noexcept(is_nothrow_move_constructible_v<_Range>) + : _M_r(std::move(__t)) + { } + + owning_view(owning_view&&) = default; + owning_view& operator=(owning_view&&) = default; + + constexpr _Range& + base() & noexcept + { return _M_r; } + + constexpr const _Range& + base() const& noexcept + { return _M_r; } + + constexpr _Range&& + base() && noexcept + { return std::move(_M_r); } + + constexpr const _Range&& + base() const&& noexcept + { return std::move(_M_r); } + + constexpr iterator_t<_Range> + begin() + { return ranges::begin(_M_r); } + + constexpr sentinel_t<_Range> + end() + { return ranges::end(_M_r); } + + constexpr auto + begin() const requires range + { return ranges::begin(_M_r); } + + constexpr auto + end() const requires range + { return ranges::end(_M_r); } + + constexpr bool + empty() requires requires { ranges::empty(_M_r); } + { return ranges::empty(_M_r); } + + constexpr bool + empty() const requires requires { ranges::empty(_M_r); } + { return ranges::empty(_M_r); } + + constexpr auto + size() requires sized_range<_Range> + { return ranges::size(_M_r); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_r); } + + constexpr auto + data() requires contiguous_range<_Range> + { return ranges::data(_M_r); } + + constexpr auto + data() const requires contiguous_range + { return ranges::data(_M_r); } + }; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + concept __can_ref_view = requires { ref_view{std::declval<_Range>()}; }; + + template + concept __can_owning_view = requires { owning_view{std::declval<_Range>()}; }; + } // namespace __detail + + struct _All : __adaptor::_RangeAdaptorClosure<_All> + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (view>) + return is_nothrow_constructible_v, _Range>; + else if constexpr (__detail::__can_ref_view<_Range>) + return true; + else + return noexcept(owning_view{std::declval<_Range>()}); + } + + template + requires view> + || __detail::__can_ref_view<_Range> + || __detail::__can_owning_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + noexcept(_S_noexcept<_Range>()) + { + if constexpr (view>) + return std::forward<_Range>(__r); + else if constexpr (__detail::__can_ref_view<_Range>) + return ref_view{std::forward<_Range>(__r)}; + else + return owning_view{std::forward<_Range>(__r)}; + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + inline constexpr _All all; + + template + using all_t = decltype(all(std::declval<_Range>())); + } // namespace views + + namespace __detail + { + template + struct __non_propagating_cache + { + // When _Tp is not an object type (e.g. is a reference type), we make + // __non_propagating_cache<_Tp> empty rather than ill-formed so that + // users can easily conditionally declare data members with this type + // (such as join_view::_M_inner). + }; + + template + requires is_object_v<_Tp> + struct __non_propagating_cache<_Tp> + : protected _Optional_base<_Tp> + { + __non_propagating_cache() = default; + + constexpr + __non_propagating_cache(const __non_propagating_cache&) noexcept + { } + + constexpr + __non_propagating_cache(__non_propagating_cache&& __other) noexcept + { __other._M_reset(); } + + constexpr __non_propagating_cache& + operator=(const __non_propagating_cache& __other) noexcept + { + if (std::__addressof(__other) != this) + this->_M_reset(); + return *this; + } + + constexpr __non_propagating_cache& + operator=(__non_propagating_cache&& __other) noexcept + { + this->_M_reset(); + __other._M_reset(); + return *this; + } + + constexpr __non_propagating_cache& + operator=(_Tp __val) + { + this->_M_reset(); + this->_M_payload._M_construct(std::move(__val)); + return *this; + } + + constexpr explicit + operator bool() const noexcept + { return this->_M_is_engaged(); } + + constexpr _Tp& + operator*() noexcept + { return this->_M_get(); } + + constexpr const _Tp& + operator*() const noexcept + { return this->_M_get(); } + + template + constexpr _Tp& + _M_emplace_deref(const _Iter& __i) + { + this->_M_reset(); + auto __f = [] (auto& __x) { return *__x; }; + this->_M_payload._M_apply(_Optional_func{__f}, __i); + return this->_M_get(); + } + }; + + template + struct _CachedPosition + { + constexpr bool + _M_has_value() const + { return false; } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(false); + __builtin_unreachable(); + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>&) const + { } + }; + + template + struct _CachedPosition<_Range> + : protected __non_propagating_cache> + { + constexpr bool + _M_has_value() const + { return this->_M_is_engaged(); } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(_M_has_value()); + return **this; + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + std::construct_at(std::__addressof(this->_M_payload._M_payload), + in_place, __it); + this->_M_payload._M_engaged = true; + } + }; + + template + requires (sizeof(range_difference_t<_Range>) + <= sizeof(iterator_t<_Range>)) + struct _CachedPosition<_Range> + { + private: + range_difference_t<_Range> _M_offset = -1; + + public: + _CachedPosition() = default; + + constexpr + _CachedPosition(const _CachedPosition&) = default; + + constexpr + _CachedPosition(_CachedPosition&& __other) noexcept + { *this = std::move(__other); } + + constexpr _CachedPosition& + operator=(const _CachedPosition&) = default; + + constexpr _CachedPosition& + operator=(_CachedPosition&& __other) noexcept + { + // Propagate the cached offset, but invalidate the source. + _M_offset = __other._M_offset; + __other._M_offset = -1; + return *this; + } + + constexpr bool + _M_has_value() const + { return _M_offset >= 0; } + + constexpr iterator_t<_Range> + _M_get(_Range& __r) const + { + __glibcxx_assert(_M_has_value()); + return ranges::begin(__r) + _M_offset; + } + + constexpr void + _M_set(_Range& __r, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + _M_offset = __it - ranges::begin(__r); + } + }; + } // namespace __detail + + namespace __detail + { + template + struct __filter_view_iter_cat + { }; + + template + struct __filter_view_iter_cat<_Base> + { + private: + static auto + _S_iter_cat() + { + using _Cat = typename iterator_traits>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + } // namespace __detail + + template> _Pred> + requires view<_Vp> && is_object_v<_Pred> + class filter_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator : __detail::__filter_view_iter_cat<_Vp> + { + private: + static constexpr auto + _S_iter_concept() + { + if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Vp>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend filter_view; + + using _Vp_iter = iterator_t<_Vp>; + + _Vp_iter _M_current = _Vp_iter(); + filter_view* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in __filter_view_iter_cat + using value_type = range_value_t<_Vp>; + using difference_type = range_difference_t<_Vp>; + + _Iterator() requires default_initializable<_Vp_iter> = default; + + constexpr + _Iterator(filter_view* __parent, _Vp_iter __current) + : _M_current(std::move(__current)), + _M_parent(__parent) + { } + + constexpr const _Vp_iter& + base() const & noexcept + { return _M_current; } + + constexpr _Vp_iter + base() && + { return std::move(_M_current); } + + constexpr range_reference_t<_Vp> + operator*() const + { return *_M_current; } + + constexpr _Vp_iter + operator->() const + requires __detail::__has_arrow<_Vp_iter> + && copyable<_Vp_iter> + { return _M_current; } + + constexpr _Iterator& + operator++() + { + _M_current = ranges::find_if(std::move(++_M_current), + ranges::end(_M_parent->_M_base), + std::ref(*_M_parent->_M_pred)); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Vp> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Vp> + { + do + --_M_current; + while (!std::__invoke(*_M_parent->_M_pred, *_M_current)); + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Vp> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Vp_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr range_rvalue_reference_t<_Vp> + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable<_Vp_iter> + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + struct _Sentinel + { + private: + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr bool + __equal(const _Iterator& __i) const + { return __i._M_current == _M_end; } + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(filter_view* __parent) + : _M_end(ranges::end(__parent->_M_base)) + { } + + constexpr sentinel_t<_Vp> + base() const + { return _M_end; } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + }; + + _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + filter_view() requires (default_initializable<_Vp> + && default_initializable<_Pred>) + = default; + + constexpr + filter_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr _Iterator + begin() + { + if (_M_cached_begin._M_has_value()) + return {this, _M_cached_begin._M_get(_M_base)}; + + __glibcxx_assert(_M_pred.has_value()); + auto __it = ranges::find_if(ranges::begin(_M_base), + ranges::end(_M_base), + std::ref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return {this, std::move(__it)}; + } + + constexpr auto + end() + { + if constexpr (common_range<_Vp>) + return _Iterator{this, ranges::end(_M_base)}; + else + return _Sentinel{this}; + } + }; + + template + filter_view(_Range&&, _Pred) -> filter_view, _Pred>; + + namespace views + { + namespace __detail + { + template + concept __can_filter_view + = requires { filter_view(std::declval<_Range>(), std::declval<_Pred>()); }; + } // namespace __detail + + struct _Filter : __adaptor::_RangeAdaptor<_Filter> + { + template + requires __detail::__can_filter_view<_Range, _Pred> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const + { + return filter_view(std::forward<_Range>(__r), std::forward<_Pred>(__p)); + } + + using _RangeAdaptor<_Filter>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Filter filter; + } // namespace views + +#if __cpp_lib_ranges >= 202207L // C++ >= 23 + template +#else + template +#endif + requires view<_Vp> && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vp>> + && std::__detail::__can_reference>> + class transform_view : public view_interface> + { + private: + template + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + struct __iter_cat + { }; + + template + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using _Base = transform_view::_Base<_Const>; + using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; + if constexpr (is_lvalue_reference_v<_Res>) + { + using _Cat + = typename iterator_traits>::iterator_category; + if constexpr (derived_from<_Cat, contiguous_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template + struct _Sentinel; + + template + struct _Iterator : __iter_cat<_Const> + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = transform_view::_Base<_Const>; + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Base>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + using _Base_iter = iterator_t<_Base>; + + _Base_iter _M_current = _Base_iter(); + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in __transform_view_iter_cat + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() requires default_initializable<_Base_iter> = default; + + constexpr + _Iterator(_Parent* __parent, _Base_iter __current) + : _M_current(std::move(__current)), + _M_parent(__parent) + { } + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Base_iter> + : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent) + { } + + constexpr const _Base_iter& + base() const & noexcept + { return _M_current; } + + constexpr _Base_iter + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current))) + { return std::__invoke(*_M_parent->_M_fun, *_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Base_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable<_Base_iter> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires random_access_range<_Base> + { return {__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {__i._M_parent, __i._M_current - __n}; } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3483. transform_view::iterator's difference is overconstrained + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return __x._M_current - __y._M_current; } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) noexcept(noexcept(*__i)) + { + if constexpr (is_lvalue_reference_v) + return std::move(*__i); + else + return *__i; + } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = transform_view::_Base<_Const>; + + template + constexpr auto + __distance_from(const _Iterator<_Const2>& __i) const + { return _M_end - __i._M_current; } + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_current == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __i) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return -__y.__distance_from(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x) + { return __y.__distance_from(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + + public: + transform_view() requires (default_initializable<_Vp> + && default_initializable<_Fp>) + = default; + + constexpr + transform_view(_Vp __base, _Fp __fun) + : _M_base(std::move(__base)), _M_fun(std::move(__fun)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base ; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _Iterator + begin() + { return _Iterator{this, ranges::begin(_M_base)}; } + + constexpr _Iterator + begin() const + requires range + && regular_invocable> + { return _Iterator{this, ranges::begin(_M_base)}; } + + constexpr _Sentinel + end() + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() requires common_range<_Vp> + { return _Iterator{this, ranges::end(_M_base)}; } + + constexpr _Sentinel + end() const + requires range + && regular_invocable> + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() const + requires common_range + && regular_invocable> + { return _Iterator{this, ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + transform_view(_Range&&, _Fp) -> transform_view, _Fp>; + + namespace views + { + namespace __detail + { + template + concept __can_transform_view + = requires { transform_view(std::declval<_Range>(), std::declval<_Fp>()); }; + } // namespace __detail + + struct _Transform : __adaptor::_RangeAdaptor<_Transform> + { + template + requires __detail::__can_transform_view<_Range, _Fp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const + { + return transform_view(std::forward<_Range>(__r), std::forward<_Fp>(__f)); + } + + using _RangeAdaptor<_Transform>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Transform transform; + } // namespace views + + template + class take_view : public view_interface> + { + private: + template + using _CI = counted_iterator< + iterator_t<__detail::__maybe_const_t<_Const, _Vp>>>; + + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + friend constexpr bool + operator==(const _CI<_Const>& __y, const _Sentinel& __x) + { return __y.count() == 0 || __y.base() == __x._M_end; } + + template> + requires sentinel_for, iterator_t<_Base2>> + friend constexpr bool + operator==(const _CI<_OtherConst>& __y, const _Sentinel& __x) + { return __y.count() == 0 || __y.base() == __x._M_end; } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + public: + take_view() requires default_initializable<_Vp> = default; + + constexpr + take_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(std::move(__count)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator(ranges::begin(_M_base), __sz); + } + } + else + return counted_iterator(ranges::begin(_M_base), _M_count); + } + + constexpr auto + begin() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator(ranges::begin(_M_base), __sz); + } + } + else + return counted_iterator(ranges::begin(_M_base), _M_count); + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + end() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + size() requires sized_range<_Vp> + { + auto __n = ranges::size(_M_base); + return std::min(__n, static_cast(_M_count)); + } + + constexpr auto + size() const requires sized_range + { + auto __n = ranges::size(_M_base); + return std::min(__n, static_cast(_M_count)); + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3447. Deduction guides for take_view and drop_view have different + // constraints + template + take_view(_Range&&, range_difference_t<_Range>) + -> take_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_empty_view = false; + + template + inline constexpr bool __is_empty_view> = true; + + template + inline constexpr bool __is_basic_string_view = false; + + template + inline constexpr bool __is_basic_string_view> + = true; + + using ranges::__detail::__is_subrange; + + template + inline constexpr bool __is_iota_view = false; + + template + inline constexpr bool __is_iota_view> = true; + + template + inline constexpr bool __is_repeat_view = false; + + template + constexpr auto + __take_of_repeat_view(_Range&&, range_difference_t<_Range>); // defined later + + template + concept __can_take_view + = requires { take_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } // namespace __detail + + struct _Take : __adaptor::_RangeAdaptor<_Take> + { + template> + requires __detail::__can_take_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { + using _Tp = remove_cvref_t<_Range>; + if constexpr (__detail::__is_empty_view<_Tp>) + return _Tp(); + else if constexpr (random_access_range<_Tp> + && sized_range<_Tp> + && (std::__detail::__is_span<_Tp> + || __detail::__is_basic_string_view<_Tp> + || __detail::__is_subrange<_Tp> + || __detail::__is_iota_view<_Tp>)) + { + __n = std::min<_Dp>(ranges::distance(__r), __n); + auto __begin = ranges::begin(__r); + auto __end = __begin + __n; + if constexpr (std::__detail::__is_span<_Tp>) + return span(__begin, __end); + else if constexpr (__detail::__is_basic_string_view<_Tp>) + return _Tp(__begin, __end); + else if constexpr (__detail::__is_subrange<_Tp>) + return subrange>(__begin, __end); + else + return iota_view(*__begin, *__end); + } + else if constexpr (__detail::__is_repeat_view<_Tp>) + return __detail::__take_of_repeat_view(std::forward<_Range>(__r), __n); + else + return take_view(std::forward<_Range>(__r), __n); + } + + using _RangeAdaptor<_Take>::operator(); + static constexpr int _S_arity = 2; + // The count argument of views::take is not always simple -- it can be + // e.g. a move-only class that's implicitly convertible to the difference + // type. But an integer-like count argument is surely simple. + template + static constexpr bool _S_has_simple_extra_args + = ranges::__detail::__is_integer_like<_Tp>; + }; + + inline constexpr _Take take; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class take_while_view : public view_interface> + { + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + const _Pred* _M_pred = nullptr; + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + : _M_end(__end), _M_pred(__pred) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(__s._M_end), _M_pred(__s._M_pred) + { } + + constexpr sentinel_t<_Base> + base() const { return _M_end; } + + friend constexpr bool + operator==(const iterator_t<_Base>& __x, const _Sentinel& __y) + { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } + + template> + requires sentinel_for, iterator_t<_Base2>> + friend constexpr bool + operator==(const iterator_t<_Base2>& __x, const _Sentinel& __y) + { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Pred> _M_pred; + + public: + take_while_view() requires (default_initializable<_Vp> + && default_initializable<_Pred>) + = default; + + constexpr + take_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::begin(_M_base); } + + constexpr auto + begin() const requires range + && indirect_unary_predicate> + { return ranges::begin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + + constexpr auto + end() const requires range + && indirect_unary_predicate> + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + }; + + template + take_while_view(_Range&&, _Pred) + -> take_while_view, _Pred>; + + namespace views + { + namespace __detail + { + template + concept __can_take_while_view + = requires { take_while_view(std::declval<_Range>(), std::declval<_Pred>()); }; + } // namespace __detail + + struct _TakeWhile : __adaptor::_RangeAdaptor<_TakeWhile> + { + template + requires __detail::__can_take_while_view<_Range, _Pred> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const + { + return take_while_view(std::forward<_Range>(__r), std::forward<_Pred>(__p)); + } + + using _RangeAdaptor<_TakeWhile>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _TakeWhile take_while; + } // namespace views + + template + class drop_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies + // both random_access_range and sized_range. Otherwise, cache its result. + static constexpr bool _S_needs_cached_begin + = !(random_access_range && sized_range); + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + drop_view() requires default_initializable<_Vp> = default; + + constexpr + drop_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(__count) + { __glibcxx_assert(__count >= 0); } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + // This overload is disabled for simple views with constant-time begin(). + constexpr auto + begin() + requires (!(__detail::__simple_view<_Vp> + && random_access_range + && sized_range)) + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + auto __it = ranges::next(ranges::begin(_M_base), + _M_count, ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3482. drop_view's const begin should additionally require sized_range + constexpr auto + begin() const + requires random_access_range && sized_range + { + return ranges::next(ranges::begin(_M_base), _M_count, + ranges::end(_M_base)); + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::end(_M_base); } + + constexpr auto + end() const requires range + { return ranges::end(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + + constexpr auto + size() const requires sized_range + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + }; + + template + drop_view(_Range&&, range_difference_t<_Range>) + -> drop_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + constexpr auto + __drop_of_repeat_view(_Range&&, range_difference_t<_Range>); // defined later + + template + concept __can_drop_view + = requires { drop_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } // namespace __detail + + struct _Drop : __adaptor::_RangeAdaptor<_Drop> + { + template> + requires __detail::__can_drop_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { + using _Tp = remove_cvref_t<_Range>; + if constexpr (__detail::__is_empty_view<_Tp>) + return _Tp(); + else if constexpr (random_access_range<_Tp> + && sized_range<_Tp> + && (std::__detail::__is_span<_Tp> + || __detail::__is_basic_string_view<_Tp> + || __detail::__is_iota_view<_Tp> + || __detail::__is_subrange<_Tp>)) + { + __n = std::min<_Dp>(ranges::distance(__r), __n); + auto __begin = ranges::begin(__r) + __n; + auto __end = ranges::end(__r); + if constexpr (std::__detail::__is_span<_Tp>) + return span(__begin, __end); + else if constexpr (__detail::__is_subrange<_Tp>) + { + if constexpr (_Tp::_S_store_size) + { + using ranges::__detail::__to_unsigned_like; + auto __m = ranges::distance(__r) - __n; + return _Tp(__begin, __end, __to_unsigned_like(__m)); + } + else + return _Tp(__begin, __end); + } + else + return _Tp(__begin, __end); + } + else if constexpr (__detail::__is_repeat_view<_Tp>) + return __detail::__drop_of_repeat_view(std::forward<_Range>(__r), __n); + else + return drop_view(std::forward<_Range>(__r), __n); + } + + using _RangeAdaptor<_Drop>::operator(); + static constexpr int _S_arity = 2; + template + static constexpr bool _S_has_simple_extra_args + = _Take::_S_has_simple_extra_args<_Tp>; + }; + + inline constexpr _Drop drop; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class drop_while_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + drop_while_view() requires (default_initializable<_Vp> + && default_initializable<_Pred>) + = default; + + constexpr + drop_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() + { + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + __glibcxx_assert(_M_pred.has_value()); + auto __it = ranges::find_if_not(ranges::begin(_M_base), + ranges::end(_M_base), + std::cref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + constexpr auto + end() + { return ranges::end(_M_base); } + }; + + template + drop_while_view(_Range&&, _Pred) + -> drop_while_view, _Pred>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + concept __can_drop_while_view + = requires { drop_while_view(std::declval<_Range>(), std::declval<_Pred>()); }; + } // namespace __detail + + struct _DropWhile : __adaptor::_RangeAdaptor<_DropWhile> + { + template + requires __detail::__can_drop_while_view<_Range, _Pred> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const + { + return drop_while_view(std::forward<_Range>(__r), + std::forward<_Pred>(__p)); + } + + using _RangeAdaptor<_DropWhile>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _DropWhile drop_while; + } // namespace views + + namespace __detail + { + template + constexpr _Tp& + __as_lvalue(_Tp&& __t) + { return static_cast<_Tp&>(__t); } + } // namespace __detail + + template + requires view<_Vp> && input_range> + class join_view : public view_interface> + { + private: + using _InnerRange = range_reference_t<_Vp>; + + template + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + using _Outer_iter = iterator_t<_Base<_Const>>; + + template + using _Inner_iter = iterator_t>>; + + template + static constexpr bool _S_ref_is_glvalue + = is_reference_v>>; + + template + struct __iter_cat + { }; + + template + requires _S_ref_is_glvalue<_Const> + && forward_range<_Base<_Const>> + && forward_range>> + struct __iter_cat<_Const> + { + private: + static constexpr auto + _S_iter_cat() + { + using _Outer_iter = join_view::_Outer_iter<_Const>; + using _Inner_iter = join_view::_Inner_iter<_Const>; + using _OuterCat = typename iterator_traits<_Outer_iter>::iterator_category; + using _InnerCat = typename iterator_traits<_Inner_iter>::iterator_category; + if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag> + && derived_from<_InnerCat, bidirectional_iterator_tag> + && common_range>>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, forward_iterator_tag> + && derived_from<_InnerCat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template + struct _Sentinel; + + template + struct _Iterator : __iter_cat<_Const> + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = join_view::_Base<_Const>; + + friend join_view; + + static constexpr bool _S_ref_is_glvalue + = join_view::_S_ref_is_glvalue<_Const>; + + constexpr void + _M_satisfy() + { + auto __update_inner = [this] (const iterator_t<_Base>& __x) -> auto&& { + if constexpr (_S_ref_is_glvalue) + return *__x; + else + return _M_parent->_M_inner._M_emplace_deref(__x); + }; + + _Outer_iter& __outer = _M_get_outer(); + for (; __outer != ranges::end(_M_parent->_M_base); ++__outer) + { + auto&& __inner = __update_inner(__outer); + _M_inner = ranges::begin(__inner); + if (_M_inner != ranges::end(__inner)) + return; + } + + if constexpr (_S_ref_is_glvalue) + _M_inner.reset(); + } + + static constexpr auto + _S_iter_concept() + { + if constexpr (_S_ref_is_glvalue + && bidirectional_range<_Base> + && bidirectional_range> + && common_range>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && forward_range<_Base> + && forward_range>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + using _Outer_iter = join_view::_Outer_iter<_Const>; + using _Inner_iter = join_view::_Inner_iter<_Const>; + + constexpr _Outer_iter& + _M_get_outer() + { + if constexpr (forward_range<_Base>) + return _M_outer; + else + return *_M_parent->_M_outer; + } + + constexpr const _Outer_iter& + _M_get_outer() const + { + if constexpr (forward_range<_Base>) + return _M_outer; + else + return *_M_parent->_M_outer; + } + + constexpr + _Iterator(_Parent* __parent, _Outer_iter __outer) requires forward_range<_Base> + : _M_outer(std::move(__outer)), _M_parent(__parent) + { _M_satisfy(); } + + constexpr explicit + _Iterator(_Parent* __parent) requires (!forward_range<_Base>) + : _M_parent(__parent) + { _M_satisfy(); } + + [[no_unique_address]] + __detail::__maybe_present_t, _Outer_iter> _M_outer; + optional<_Inner_iter> _M_inner; + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in __join_view_iter_cat + using value_type = range_value_t>; + using difference_type + = common_type_t, + range_difference_t>>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Outer_iter> + && convertible_to, _Inner_iter> + : _M_outer(std::move(__i._M_outer)), _M_inner(std::move(__i._M_inner)), + _M_parent(__i._M_parent) + { } + + constexpr decltype(auto) + operator*() const + { return **_M_inner; } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3500. join_view::iterator::operator->() is bogus + constexpr _Inner_iter + operator->() const + requires __detail::__has_arrow<_Inner_iter> + && copyable<_Inner_iter> + { return *_M_inner; } + + constexpr _Iterator& + operator++() + { + auto&& __inner_range = [this] () -> auto&& { + if constexpr (_S_ref_is_glvalue) + return *_M_get_outer(); + else + return *_M_parent->_M_inner; + }(); + if (++*_M_inner == ranges::end(__inner_range)) + { + ++_M_get_outer(); + _M_satisfy(); + } + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires _S_ref_is_glvalue && forward_range<_Base> + && forward_range> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + if (_M_outer == ranges::end(_M_parent->_M_base)) + _M_inner = ranges::end(__detail::__as_lvalue(*--_M_outer)); + while (*_M_inner == ranges::begin(__detail::__as_lvalue(*_M_outer))) + *_M_inner = ranges::end(__detail::__as_lvalue(*--_M_outer)); + --*_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires _S_ref_is_glvalue + && forward_range<_Base> + && equality_comparable<_Inner_iter> + { + return (__x._M_outer == __y._M_outer + && __x._M_inner == __y._M_inner); + } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(*__i._M_inner))) + { return ranges::iter_move(*__i._M_inner); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(*__x._M_inner, *__y._M_inner))) + requires indirectly_swappable<_Inner_iter> + { return ranges::iter_swap(*__x._M_inner, *__y._M_inner); } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = join_view::_Base<_Const>; + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_get_outer() == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Parent* __parent) + : _M_end(ranges::end(__parent->_M_base)) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + [[no_unique_address]] + __detail::__maybe_present_t, + __detail::__non_propagating_cache>> _M_outer; + [[no_unique_address]] + __detail::__non_propagating_cache> _M_inner; + + public: + join_view() requires default_initializable<_Vp> = default; + + constexpr explicit + join_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (forward_range<_Vp>) + { + constexpr bool __use_const + = (__detail::__simple_view<_Vp> + && is_reference_v>); + return _Iterator<__use_const>{this, ranges::begin(_M_base)}; + } + else + { + _M_outer = ranges::begin(_M_base); + return _Iterator{this}; + } + } + + constexpr auto + begin() const + requires forward_range + && is_reference_v> + && input_range> + { + return _Iterator{this, ranges::begin(_M_base)}; + } + + constexpr auto + end() + { + if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange> + && forward_range<_InnerRange> + && common_range<_Vp> && common_range<_InnerRange>) + return _Iterator<__detail::__simple_view<_Vp>>{this, + ranges::end(_M_base)}; + else + return _Sentinel<__detail::__simple_view<_Vp>>{this}; + } + + constexpr auto + end() const + requires forward_range + && is_reference_v> + && input_range> + { + if constexpr (is_reference_v> + && forward_range> + && common_range + && common_range>) + return _Iterator{this, ranges::end(_M_base)}; + else + return _Sentinel{this}; + } + }; + + template + explicit join_view(_Range&&) -> join_view>; + + namespace views + { + namespace __detail + { + template + concept __can_join_view + = requires { join_view>{std::declval<_Range>()}; }; + } // namespace __detail + + struct _Join : __adaptor::_RangeAdaptorClosure<_Join> + { + template + requires __detail::__can_join_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3474. Nesting join_views is broken because of CTAD + return join_view>{std::forward<_Range>(__r)}; + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + inline constexpr _Join join; + } // namespace views + + namespace __detail + { + template + struct __require_constant; + + template + concept __tiny_range = sized_range<_Range> + && requires + { typename __require_constant::size()>; } + && (remove_reference_t<_Range>::size() <= 1); + + template + struct __lazy_split_view_outer_iter_cat + { }; + + template + struct __lazy_split_view_outer_iter_cat<_Base> + { using iterator_category = input_iterator_tag; }; + + template + struct __lazy_split_view_inner_iter_cat + { }; + + template + struct __lazy_split_view_inner_iter_cat<_Base> + { + private: + static constexpr auto + _S_iter_cat() + { + using _Cat = typename iterator_traits>::iterator_category; + if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + } + + template + requires view<_Vp> && view<_Pattern> + && indirectly_comparable, iterator_t<_Pattern>, + ranges::equal_to> + && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>) + class lazy_split_view : public view_interface> + { + private: + template + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + struct _InnerIter; + + template + struct _OuterIter + : __detail::__lazy_split_view_outer_iter_cat<_Base<_Const>> + { + private: + using _Parent = __detail::__maybe_const_t<_Const, lazy_split_view>; + using _Base = lazy_split_view::_Base<_Const>; + + constexpr bool + __at_end() const + { return __current() == ranges::end(_M_parent->_M_base) && !_M_trailing_empty; } + + // [range.lazy.split.outer] p1 + // Many of the following specifications refer to the notional member + // current of outer-iterator. current is equivalent to current_ if + // V models forward_range, and parent_->current_ otherwise. + constexpr auto& + __current() noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return *_M_parent->_M_current; + } + + constexpr auto& + __current() const noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return *_M_parent->_M_current; + } + + _Parent* _M_parent = nullptr; + + [[no_unique_address]] + __detail::__maybe_present_t, + iterator_t<_Base>> _M_current; + bool _M_trailing_empty = false; + + public: + using iterator_concept = __conditional_t, + forward_iterator_tag, + input_iterator_tag>; + // iterator_category defined in __lazy_split_view_outer_iter_cat + using difference_type = range_difference_t<_Base>; + + struct value_type : view_interface + { + private: + _OuterIter _M_i = _OuterIter(); + + public: + value_type() = default; + + constexpr explicit + value_type(_OuterIter __i) + : _M_i(std::move(__i)) + { } + + constexpr _InnerIter<_Const> + begin() const + { return _InnerIter<_Const>{_M_i}; } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + }; + + _OuterIter() = default; + + constexpr explicit + _OuterIter(_Parent* __parent) requires (!forward_range<_Base>) + : _M_parent(__parent) + { } + + constexpr + _OuterIter(_Parent* __parent, iterator_t<_Base> __current) + requires forward_range<_Base> + : _M_parent(__parent), + _M_current(std::move(__current)) + { } + + constexpr + _OuterIter(_OuterIter __i) + requires _Const + && convertible_to, iterator_t<_Base>> + : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)), + _M_trailing_empty(__i._M_trailing_empty) + { } + + constexpr value_type + operator*() const + { return value_type{*this}; } + + constexpr _OuterIter& + operator++() + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3505. lazy_split_view::outer-iterator::operator++ misspecified + const auto __end = ranges::end(_M_parent->_M_base); + if (__current() == __end) + { + _M_trailing_empty = false; + return *this; + } + const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; + if (__pbegin == __pend) + ++__current(); + else if constexpr (__detail::__tiny_range<_Pattern>) + { + __current() = ranges::find(std::move(__current()), __end, + *__pbegin); + if (__current() != __end) + { + ++__current(); + if (__current() == __end) + _M_trailing_empty = true; + } + } + else + do + { + auto [__b, __p] + = ranges::mismatch(__current(), __end, __pbegin, __pend); + if (__p == __pend) + { + __current() = __b; + if (__current() == __end) + _M_trailing_empty = true; + break; + } + } while (++__current() != __end); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Base>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _OuterIter& __x, const _OuterIter& __y) + requires forward_range<_Base> + { + return __x._M_current == __y._M_current + && __x._M_trailing_empty == __y._M_trailing_empty; + } + + friend constexpr bool + operator==(const _OuterIter& __x, default_sentinel_t) + { return __x.__at_end(); }; + + friend _OuterIter; + friend _InnerIter<_Const>; + }; + + template + struct _InnerIter + : __detail::__lazy_split_view_inner_iter_cat<_Base<_Const>> + { + private: + using _Base = lazy_split_view::_Base<_Const>; + + constexpr bool + __at_end() const + { + auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern}; + auto __end = ranges::end(_M_i._M_parent->_M_base); + if constexpr (__detail::__tiny_range<_Pattern>) + { + const auto& __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + return *__cur == *__pcur; + } + else + { + auto __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + do + { + if (*__cur != *__pcur) + return false; + if (++__pcur == __pend) + return true; + } while (++__cur != __end); + return false; + } + } + + constexpr auto& + _M_i_current() noexcept + { return _M_i.__current(); } + + constexpr auto& + _M_i_current() const noexcept + { return _M_i.__current(); } + + _OuterIter<_Const> _M_i = _OuterIter<_Const>(); + bool _M_incremented = false; + + public: + using iterator_concept + = typename _OuterIter<_Const>::iterator_concept; + // iterator_category defined in __lazy_split_view_inner_iter_cat + using value_type = range_value_t<_Base>; + using difference_type = range_difference_t<_Base>; + + _InnerIter() = default; + + constexpr explicit + _InnerIter(_OuterIter<_Const> __i) + : _M_i(std::move(__i)) + { } + + constexpr const iterator_t<_Base>& + base() const& noexcept + { return _M_i_current(); } + + constexpr iterator_t<_Base> + base() && requires forward_range<_Vp> + { return std::move(_M_i_current()); } + + constexpr decltype(auto) + operator*() const + { return *_M_i_current(); } + + constexpr _InnerIter& + operator++() + { + _M_incremented = true; + if constexpr (!forward_range<_Base>) + if constexpr (_Pattern::size() == 0) + return *this; + ++_M_i_current(); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Base>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _InnerIter& __x, const _InnerIter& __y) + requires forward_range<_Base> + { return __x._M_i == __y._M_i; } + + friend constexpr bool + operator==(const _InnerIter& __x, default_sentinel_t) + { return __x.__at_end(); } + + friend constexpr decltype(auto) + iter_move(const _InnerIter& __i) + noexcept(noexcept(ranges::iter_move(__i._M_i_current()))) + { return ranges::iter_move(__i._M_i_current()); } + + friend constexpr void + iter_swap(const _InnerIter& __x, const _InnerIter& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_i_current(), + __y._M_i_current()))) + requires indirectly_swappable> + { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } + }; + + _Vp _M_base = _Vp(); + _Pattern _M_pattern = _Pattern(); + [[no_unique_address]] + __detail::__maybe_present_t, + __detail::__non_propagating_cache>> _M_current; + + + public: + lazy_split_view() requires (default_initializable<_Vp> + && default_initializable<_Pattern>) + = default; + + constexpr + lazy_split_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view>> + constexpr + lazy_split_view(_Range&& __r, range_value_t<_Range> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (forward_range<_Vp>) + { + constexpr bool __simple + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _OuterIter<__simple>{this, ranges::begin(_M_base)}; + } + else + { + _M_current = ranges::begin(_M_base); + return _OuterIter{this}; + } + } + + constexpr auto + begin() const requires forward_range<_Vp> && forward_range + { + return _OuterIter{this, ranges::begin(_M_base)}; + } + + constexpr auto + end() requires forward_range<_Vp> && common_range<_Vp> + { + constexpr bool __simple + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _OuterIter<__simple>{this, ranges::end(_M_base)}; + } + + constexpr auto + end() const + { + if constexpr (forward_range<_Vp> + && forward_range + && common_range) + return _OuterIter{this, ranges::end(_M_base)}; + else + return default_sentinel; + } + }; + + template + lazy_split_view(_Range&&, _Pattern&&) + -> lazy_split_view, views::all_t<_Pattern>>; + + template + lazy_split_view(_Range&&, range_value_t<_Range>) + -> lazy_split_view, single_view>>; + + namespace views + { + namespace __detail + { + template + concept __can_lazy_split_view + = requires { lazy_split_view(std::declval<_Range>(), std::declval<_Pattern>()); }; + } // namespace __detail + + struct _LazySplit : __adaptor::_RangeAdaptor<_LazySplit> + { + template + requires __detail::__can_lazy_split_view<_Range, _Pattern> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const + { + return lazy_split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); + } + + using _RangeAdaptor<_LazySplit>::operator(); + static constexpr int _S_arity = 2; + // The pattern argument of views::lazy_split is not always simple -- it can be + // a non-view range, the value category of which affects whether the call + // is well-formed. But a scalar or a view pattern argument is surely + // simple. + template + static constexpr bool _S_has_simple_extra_args + = is_scalar_v<_Pattern> || (view<_Pattern> + && copy_constructible<_Pattern>); + }; + + inline constexpr _LazySplit lazy_split; + } // namespace views + + template + requires view<_Vp> && view<_Pattern> + && indirectly_comparable, iterator_t<_Pattern>, + ranges::equal_to> + class split_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + _Pattern _M_pattern = _Pattern(); + __detail::__non_propagating_cache>> _M_cached_begin; + + struct _Iterator; + struct _Sentinel; + + public: + split_view() requires (default_initializable<_Vp> + && default_initializable<_Pattern>) + = default; + + constexpr + split_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view>> + constexpr + split_view(_Range&& __r, range_value_t<_Range> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _Iterator + begin() + { + if (!_M_cached_begin) + _M_cached_begin = _M_find_next(ranges::begin(_M_base)); + return {this, ranges::begin(_M_base), *_M_cached_begin}; + } + + constexpr auto + end() + { + if constexpr (common_range<_Vp>) + return _Iterator{this, ranges::end(_M_base), {}}; + else + return _Sentinel{this}; + } + + constexpr subrange> + _M_find_next(iterator_t<_Vp> __it) + { + auto [__b, __e] = ranges::search(subrange(__it, ranges::end(_M_base)), _M_pattern); + if (__b != ranges::end(_M_base) && ranges::empty(_M_pattern)) + { + ++__b; + ++__e; + } + return {__b, __e}; + } + + private: + struct _Iterator + { + private: + split_view* _M_parent = nullptr; + iterator_t<_Vp> _M_cur = iterator_t<_Vp>(); + subrange> _M_next = subrange>(); + bool _M_trailing_empty = false; + + friend struct _Sentinel; + + public: + using iterator_concept = forward_iterator_tag; + using iterator_category = input_iterator_tag; + using value_type = subrange>; + using difference_type = range_difference_t<_Vp>; + + _Iterator() = default; + + constexpr + _Iterator(split_view* __parent, + iterator_t<_Vp> __current, + subrange> __next) + : _M_parent(__parent), + _M_cur(std::move(__current)), + _M_next(std::move(__next)) + { } + + constexpr iterator_t<_Vp> + base() const + { return _M_cur; } + + constexpr value_type + operator*() const + { return {_M_cur, _M_next.begin()}; } + + constexpr _Iterator& + operator++() + { + _M_cur = _M_next.begin(); + if (_M_cur != ranges::end(_M_parent->_M_base)) + { + _M_cur = _M_next.end(); + if (_M_cur == ranges::end(_M_parent->_M_base)) + { + _M_trailing_empty = true; + _M_next = {_M_cur, _M_cur}; + } + else + _M_next = _M_parent->_M_find_next(_M_cur); + } + else + _M_trailing_empty = false; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { + return __x._M_cur == __y._M_cur + && __x._M_trailing_empty == __y._M_trailing_empty; + } + }; + + struct _Sentinel + { + private: + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr bool + _M_equal(const _Iterator& __x) const + { return __x._M_cur == _M_end && !__x._M_trailing_empty; } + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(split_view* __parent) + : _M_end(ranges::end(__parent->_M_base)) + { } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + }; + }; + + template + split_view(_Range&&, _Pattern&&) + -> split_view, views::all_t<_Pattern>>; + + template + split_view(_Range&&, range_value_t<_Range>) + -> split_view, single_view>>; + + namespace views + { + namespace __detail + { + template + concept __can_split_view + = requires { split_view(std::declval<_Range>(), std::declval<_Pattern>()); }; + } // namespace __detail + + struct _Split : __adaptor::_RangeAdaptor<_Split> + { + template + requires __detail::__can_split_view<_Range, _Pattern> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const + { + return split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); + } + + using _RangeAdaptor<_Split>::operator(); + static constexpr int _S_arity = 2; + template + static constexpr bool _S_has_simple_extra_args + = _LazySplit::_S_has_simple_extra_args<_Pattern>; + }; + + inline constexpr _Split split; + } // namespace views + + namespace views + { + struct _Counted + { + template + constexpr auto + operator() [[nodiscard]] (_Iter __i, iter_difference_t<_Iter> __n) const + { + if constexpr (contiguous_iterator<_Iter>) + return span(std::__to_address(__i), __n); + else if constexpr (random_access_iterator<_Iter>) + return subrange(__i, __i + __n); + else + return subrange(counted_iterator(std::move(__i), __n), + default_sentinel); + } + }; + + inline constexpr _Counted counted{}; + } // namespace views + + template + requires (!common_range<_Vp>) && copyable> + class common_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + + public: + common_view() requires default_initializable<_Vp> = default; + + constexpr explicit + common_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::begin(_M_base)); + } + + constexpr auto + begin() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t> + (ranges::begin(_M_base)); + } + + constexpr auto + end() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t> + (ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + common_view(_Range&&) -> common_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + concept __already_common = common_range<_Range> + && requires { views::all(std::declval<_Range>()); }; + + template + concept __can_common_view + = requires { common_view{std::declval<_Range>()}; }; + } // namespace __detail + + struct _Common : __adaptor::_RangeAdaptorClosure<_Common> + { + template + requires __detail::__already_common<_Range> + || __detail::__can_common_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (__detail::__already_common<_Range>) + return views::all(std::forward<_Range>(__r)); + else + return common_view{std::forward<_Range>(__r)}; + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + inline constexpr _Common common; + } // namespace views + + template + requires bidirectional_range<_Vp> + class reverse_view : public view_interface> + { + private: + static constexpr bool _S_needs_cached_begin + = !common_range<_Vp> && !(random_access_range<_Vp> + && sized_sentinel_for, + iterator_t<_Vp>>); + + _Vp _M_base = _Vp(); + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + reverse_view() requires default_initializable<_Vp> = default; + + constexpr explicit + reverse_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr reverse_iterator> + begin() + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return std::make_reverse_iterator(_M_cached_begin._M_get(_M_base)); + + auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return std::make_reverse_iterator(std::move(__it)); + } + + constexpr auto + begin() requires common_range<_Vp> + { return std::make_reverse_iterator(ranges::end(_M_base)); } + + constexpr auto + begin() const requires common_range + { return std::make_reverse_iterator(ranges::end(_M_base)); } + + constexpr reverse_iterator> + end() + { return std::make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + end() const requires common_range + { return std::make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + reverse_view(_Range&&) -> reverse_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_reversible_subrange = false; + + template + inline constexpr bool + __is_reversible_subrange, + reverse_iterator<_Iter>, + _Kind>> = true; + + template + inline constexpr bool __is_reverse_view = false; + + template + inline constexpr bool __is_reverse_view> = true; + + template + concept __can_reverse_view + = requires { reverse_view{std::declval<_Range>()}; }; + } // namespace __detail + + struct _Reverse : __adaptor::_RangeAdaptorClosure<_Reverse> + { + template + requires __detail::__is_reverse_view> + || __detail::__is_reversible_subrange> + || __detail::__can_reverse_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + using _Tp = remove_cvref_t<_Range>; + if constexpr (__detail::__is_reverse_view<_Tp>) + return std::forward<_Range>(__r).base(); + else if constexpr (__detail::__is_reversible_subrange<_Tp>) + { + using _Iter = decltype(ranges::begin(__r).base()); + if constexpr (sized_range<_Tp>) + return subrange<_Iter, _Iter, subrange_kind::sized> + {__r.end().base(), __r.begin().base(), __r.size()}; + else + return subrange<_Iter, _Iter, subrange_kind::unsized> + {__r.end().base(), __r.begin().base()}; + } + else + return reverse_view{std::forward<_Range>(__r)}; + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + inline constexpr _Reverse reverse; + } // namespace views + + namespace __detail + { +#if __cpp_lib_tuple_like // >= C++23 + template + concept __has_tuple_element = __tuple_like<_Tp> && _Nm < tuple_size_v<_Tp>; +#else + template + concept __has_tuple_element = requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires _Nm < tuple_size_v<_Tp>; + typename tuple_element_t<_Nm, _Tp>; + { std::get<_Nm>(__t) } + -> convertible_to&>; + }; +#endif + + template + concept __returnable_element + = is_reference_v<_Tp> || move_constructible>; + } + + template + requires view<_Vp> + && __detail::__has_tuple_element, _Nm> + && __detail::__has_tuple_element>, + _Nm> + && __detail::__returnable_element, _Nm> + class elements_view : public view_interface> + { + public: + elements_view() requires default_initializable<_Vp> = default; + + constexpr explicit + elements_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>) + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>) + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + end() const requires range + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() const requires common_range + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + + private: + template + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + struct __iter_cat + { }; + + template + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto _S_iter_cat() + { + using _Base = elements_view::_Base<_Const>; + using _Cat = typename iterator_traits>::iterator_category; + using _Res = decltype((std::get<_Nm>(*std::declval>()))); + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr (derived_from<_Cat, random_access_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template + struct _Sentinel; + + template + struct _Iterator : __iter_cat<_Const> + { + private: + using _Base = elements_view::_Base<_Const>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + + static constexpr decltype(auto) + _S_get_element(const iterator_t<_Base>& __i) + { + if constexpr (is_reference_v>) + return std::get<_Nm>(*__i); + else + { + using _Et = remove_cv_t>>; + return static_cast<_Et>(std::get<_Nm>(*__i)); + } + } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Base>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend _Iterator; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in elements_view::__iter_cat + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() requires default_initializable> = default; + + constexpr explicit + _Iterator(iterator_t<_Base> __current) + : _M_current(std::move(__current)) + { } + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(__i._M_current)) + { } + + constexpr const iterator_t<_Base>& + base() const& noexcept + { return _M_current; } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + { return _S_get_element(_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++_M_current; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --_M_current; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) + requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) + requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return _S_get_element(_M_current + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y._M_current < __x._M_current; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y._M_current > __x._M_current); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x._M_current > __y._M_current); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} += __y; } + + friend constexpr _Iterator + operator+(difference_type __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y + __x; } + + friend constexpr _Iterator + operator-(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} -= __y; } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3483. transform_view::iterator's difference is overconstrained + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return __x._M_current - __y._M_current; } + + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + template + constexpr bool + _M_equal(const _Iterator<_Const2>& __x) const + { return __x._M_current == _M_end; } + + template + constexpr auto + _M_distance_from(const _Iterator<_Const2>& __i) const + { return _M_end - __i._M_current; } + + using _Base = elements_view::_Base<_Const>; + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(std::move(__end)) + { } + + constexpr + _Sentinel(_Sentinel __other) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__other._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return -__y._M_distance_from(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y) + { return __x._M_distance_from(__y); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + }; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + template + using keys_view = elements_view, 0>; + + template + using values_view = elements_view, 1>; + + namespace views + { + namespace __detail + { + template + concept __can_elements_view + = requires { elements_view, _Nm>{std::declval<_Range>()}; }; + } // namespace __detail + + template + struct _Elements : __adaptor::_RangeAdaptorClosure<_Elements<_Nm>> + { + template + requires __detail::__can_elements_view<_Nm, _Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + return elements_view, _Nm>{std::forward<_Range>(__r)}; + } + + static constexpr bool _S_has_simple_call_op = true; + }; + + template + inline constexpr _Elements<_Nm> elements; + inline constexpr auto keys = elements<0>; + inline constexpr auto values = elements<1>; + } // namespace views + +#ifdef __cpp_lib_ranges_zip // C++ >= 23 + namespace __detail + { + template + concept __zip_is_common = (sizeof...(_Rs) == 1 && (common_range<_Rs> && ...)) + || (!(bidirectional_range<_Rs> && ...) && (common_range<_Rs> && ...)) + || ((random_access_range<_Rs> && ...) && (sized_range<_Rs> && ...)); + + template + constexpr auto + __tuple_transform(_Fp&& __f, _Tuple&& __tuple) + { + return std::apply([&](_Ts&&... __elts) { + return tuple...> + (std::__invoke(__f, std::forward<_Ts>(__elts))...); + }, std::forward<_Tuple>(__tuple)); + } + + template + constexpr void + __tuple_for_each(_Fp&& __f, _Tuple&& __tuple) + { + std::apply([&](_Ts&&... __elts) { + (std::__invoke(__f, std::forward<_Ts>(__elts)), ...); + }, std::forward<_Tuple>(__tuple)); + } + } // namespace __detail + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + class zip_view : public view_interface> + { + tuple<_Vs...> _M_views; + + template class _Iterator; + template class _Sentinel; + + public: + zip_view() = default; + + constexpr explicit + zip_view(_Vs... __views) + : _M_views(std::move(__views)...) + { } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vs> && ...)) + { return _Iterator(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + begin() const requires (range && ...) + { return _Iterator(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + end() requires (!(__detail::__simple_view<_Vs> && ...)) + { + if constexpr (!__detail::__zip_is_common<_Vs...>) + return _Sentinel(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range<_Vs> && ...)) + return begin() + iter_difference_t<_Iterator>(size()); + else + return _Iterator(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + end() const requires (range && ...) + { + if constexpr (!__detail::__zip_is_common) + return _Sentinel(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range && ...)) + return begin() + iter_difference_t<_Iterator>(size()); + else + return _Iterator(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + size() requires (sized_range<_Vs> && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + + constexpr auto + size() const requires (sized_range && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + }; + + template + zip_view(_Rs&&...) -> zip_view...>; + + template + inline constexpr bool enable_borrowed_range> + = (enable_borrowed_range<_Views> && ...); + + namespace __detail + { + template + concept __all_random_access + = (random_access_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + concept __all_bidirectional + = (bidirectional_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + concept __all_forward + = (forward_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + struct __zip_view_iter_cat + { }; + + template + requires __all_forward<_Const, _Views...> + struct __zip_view_iter_cat<_Const, _Views...> + { using iterator_category = input_iterator_tag; }; + } // namespace __detail + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template + class zip_view<_Vs...>::_Iterator + : public __detail::__zip_view_iter_cat<_Const, _Vs...> + { +#ifdef __clang__ // LLVM-61763 workaround + public: +#endif + tuple>...> _M_current; + + constexpr explicit + _Iterator(decltype(_M_current) __current) + : _M_current(std::move(__current)) + { } + + static auto + _S_iter_concept() + { + if constexpr (__detail::__all_random_access<_Const, _Vs...>) + return random_access_iterator_tag{}; + else if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return bidirectional_iterator_tag{}; + else if constexpr (__detail::__all_forward<_Const, _Vs...>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + +#ifndef __clang__ // LLVM-61763 workaround + template + requires (view<_Ws> && ...) && (sizeof...(_Ws) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Ws>...> + && std::__detail::__can_reference...>> + friend class zip_transform_view; +#endif + + public: + // iterator_category defined in __zip_view_iter_cat + using iterator_concept = decltype(_S_iter_concept()); + using value_type + = tuple>...>; + using difference_type + = common_type_t>...>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const + && (convertible_to, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_current(std::move(__i._M_current)) + { } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { + return *__i; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + __detail::__tuple_for_each([](auto& __i) { ++__i; }, _M_current); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires __detail::__all_forward<_Const, _Vs...> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires __detail::__all_bidirectional<_Const, _Vs...> + { + __detail::__tuple_for_each([](auto& __i) { --__i; }, _M_current); + return *this; + } + + constexpr _Iterator + operator--(int) + requires __detail::__all_bidirectional<_Const, _Vs...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) { + __i += iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) { + __i -= iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) -> decltype(auto) { + return __i[iter_difference_t<_It>(__n)]; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires (equality_comparable>> && ...) + { + if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return __x._M_current == __y._M_current; + else + return [&](index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_current)) || ...); + }(make_index_sequence{}); + } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + { + return [&](index_sequence<_Is...>) { + return ranges::min({difference_type(std::get<_Is>(__x._M_current) + - std::get<_Is>(__y._M_current))...}, + ranges::less{}, + [](difference_type __i) { + return __detail::__to_unsigned_like(__i < 0 ? -__i : __i); + }); + }(make_index_sequence{}); + } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires (indirectly_swappable>> && ...) + { + [&](index_sequence<_Is...>) { + (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...); + }(make_index_sequence{}); + } + + friend class zip_view; + }; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template + class zip_view<_Vs...>::_Sentinel + { + tuple>...> _M_end; + + constexpr explicit + _Sentinel(decltype(_M_end) __end) + : _M_end(__end) + { } + + friend class zip_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const + && (convertible_to, + sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_end(std::move(__i._M_end)) + { } + + template + requires (sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + return [&](index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_end)) || ...); + }(make_index_sequence{}); + } + + template + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + using _Ret + = common_type_t>...>; + return [&](index_sequence<_Is...>) { + return ranges::min({_Ret(std::get<_Is>(__x._M_current) - std::get<_Is>(__y._M_end))...}, + ranges::less{}, + [](_Ret __i) { + return __detail::__to_unsigned_like(__i < 0 ? -__i : __i); + }); + }(make_index_sequence{}); + } + + template + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return -(__x - __y); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_zip_view + = requires { zip_view...>(std::declval<_Ts>()...); }; + } + + struct _Zip + { + template + requires (sizeof...(_Ts) == 0 || __detail::__can_zip_view<_Ts...>) + constexpr auto + operator() [[nodiscard]] (_Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty>; + else + return zip_view...>(std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _Zip zip; + } + + namespace __detail + { + template + using __range_iter_cat + = typename iterator_traits>>::iterator_category; + } + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + class zip_transform_view : public view_interface> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + zip_view<_Vs...> _M_zip; + + using _InnerView = zip_view<_Vs...>; + + template + using __ziperator = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using __zentinel = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using _Base = __detail::__maybe_const_t<_Const, _InnerView>; + + template + struct __iter_cat + { }; + + template + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__range_iter_cat; + using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&, + range_reference_t<__maybe_const_t<_Const, _Vs>>...>; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + random_access_iterator_tag> && ...)) + return random_access_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + bidirectional_iterator_tag> && ...)) + return bidirectional_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + forward_iterator_tag> && ...)) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template class _Iterator; + template class _Sentinel; + + public: + zip_transform_view() = default; + + constexpr explicit + zip_transform_view(_Fp __fun, _Vs... __views) + : _M_fun(std::move(__fun)), _M_zip(std::move(__views)...) + { } + + constexpr auto + begin() + { return _Iterator(*this, _M_zip.begin()); } + + constexpr auto + begin() const + requires range + && regular_invocable...> + { return _Iterator(*this, _M_zip.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator(*this, _M_zip.end()); + else + return _Sentinel(_M_zip.end()); + } + + constexpr auto + end() const + requires range + && regular_invocable...> + { + if constexpr (common_range) + return _Iterator(*this, _M_zip.end()); + else + return _Sentinel(_M_zip.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_zip.size(); } + + constexpr auto + size() const requires sized_range + { return _M_zip.size(); } + }; + + template + zip_transform_view(_Fp, Rs&&...) -> zip_transform_view<_Fp, views::all_t...>; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + template + class zip_transform_view<_Fp, _Vs...>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, zip_transform_view>; + + _Parent* _M_parent = nullptr; + __ziperator<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, __ziperator<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + friend class zip_transform_view; + + public: + // iterator_category defined in zip_transform_view::__iter_cat + using iterator_concept = typename __ziperator<_Const>::iterator_concept; + using value_type + = remove_cvref_t&, + range_reference_t<__detail::__maybe_const_t<_Const, _Vs>>...>>; + using difference_type = range_difference_t<_Base<_Const>>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to<__ziperator, __ziperator<_Const>> + : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base<_Const>> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base<_Const>> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base<_Const>> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const requires random_access_range<_Base<_Const>> + { + return std::apply([&](const _Is&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, __iters[iter_difference_t<_Is>(__n)]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<__ziperator<_Const>> + { return __x._M_inner == __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner - __n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<__ziperator<_Const>, __ziperator<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + template + class zip_transform_view<_Fp, _Vs...>::_Sentinel + { + __zentinel<_Const> _M_inner; + + constexpr explicit + _Sentinel(__zentinel<_Const> __inner) + : _M_inner(__inner) + { } + + friend class zip_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to<__zentinel, __zentinel<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template + requires sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_zip_transform_view + = requires { zip_transform_view(std::declval<_Fp>(), std::declval<_Ts>()...); }; + } + + struct _ZipTransform + { + template + requires (sizeof...(_Ts) == 0) || __detail::__can_zip_transform_view<_Fp, _Ts...> + constexpr auto + operator() [[nodiscard]] (_Fp&& __f, _Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty&>>>; + else + return zip_transform_view(std::forward<_Fp>(__f), std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _ZipTransform zip_transform; + } + + template + requires view<_Vp> && (_Nm > 0) + class adjacent_view : public view_interface> + { + _Vp _M_base = _Vp(); + + template class _Iterator; + template class _Sentinel; + + struct __as_sentinel + { }; + + public: + adjacent_view() requires default_initializable<_Vp> = default; + + constexpr explicit + adjacent_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp>) + return _Iterator(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (common_range) + return _Iterator(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + + constexpr auto + size() const requires sized_range + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + }; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Vp>; + + namespace __detail + { + // Yields tuple<_Tp, ..., _Tp> with _Nm elements. + template + using __repeated_tuple = decltype(std::tuple_cat(std::declval>())); + + // For a functor F that is callable with N arguments, the expression + // declval<__unarize>(x) is equivalent to declval(x, ..., x). + template + struct __unarize + { + template + static invoke_result_t<_Fp, _Ts...> + __tuple_apply(const tuple<_Ts...>&); // not defined + + template + decltype(__tuple_apply(std::declval<__repeated_tuple<_Tp, _Nm>>())) + operator()(_Tp&&); // not defined + }; + } + + template + requires view<_Vp> && (_Nm > 0) + template + class adjacent_view<_Vp, _Nm>::_Iterator + { +#ifdef __clang__ // LLVM-61763 workaround + public: +#endif + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + array, _Nm> _M_current = array, _Nm>(); + + constexpr + _Iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) + { + for (auto& __i : _M_current) + { + __i = __first; + ranges::advance(__first, 1, __last); + } + } + + constexpr + _Iterator(__as_sentinel, iterator_t<_Base> __first, iterator_t<_Base> __last) + { + if constexpr (!bidirectional_range<_Base>) + for (auto& __it : _M_current) + __it = __last; + else + for (size_t __i = 0; __i < _Nm; ++__i) + { + _M_current[_Nm - 1 - __i] = __last; + ranges::advance(__last, -1, __first); + } + } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend class adjacent_view; + +#ifndef __clang__ // LLVM-61763 workaround + template + requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Mm>, range_reference_t<_Wp>> + && std::__detail::__can_reference, + range_reference_t<_Wp>>> + friend class adjacent_transform_view; +#endif + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type = conditional_t<_Nm == 2, + pair, range_value_t<_Base>>, + __detail::__repeated_tuple, _Nm>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + { + for (size_t __j = 0; __j < _Nm; ++__j) + _M_current[__j] = std::move(__i._M_current[__j]); + } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { return *__i; }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + for (auto& __i : _M_current) + ++__i; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + for (auto& __i : _M_current) + --__i; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i -= __x; + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires random_access_range<_Base> + { + auto __f = [&](auto& __i) -> decltype(auto) { return __i[__n]; }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current.back() == __y._M_current.back(); } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current.back() < __y._M_current.back(); } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current.back() <=> __y._M_current.back(); } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return __x._M_current.back() - __y._M_current.back(); } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires indirectly_swappable> + { + for (size_t __i = 0; __i < _Nm; __i++) + ranges::iter_swap(__l._M_current[__i], __r._M_current[__i]); + } + }; + + template + requires view<_Vp> && (_Nm > 0) + template + class adjacent_view<_Vp, _Nm>::_Sentinel + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + friend class adjacent_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() == __y._M_end; } + + template + requires sized_sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() - __y._M_end; } + + template + requires sized_sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return __y._M_end - __x._M_current.back(); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_adjacent_view + = requires { adjacent_view, _Nm>(std::declval<_Range>()); }; + } + + template + struct _Adjacent : __adaptor::_RangeAdaptorClosure<_Adjacent<_Nm>> + { + template + requires (_Nm == 0) || __detail::__can_adjacent_view<_Nm, _Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (_Nm == 0) + return views::empty>; + else + return adjacent_view, _Nm>(std::forward<_Range>(__r)); + } + }; + + template + inline constexpr _Adjacent<_Nm> adjacent; + + inline constexpr auto pairwise = adjacent<2>; + } + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + class adjacent_transform_view : public view_interface> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + adjacent_view<_Vp, _Nm> _M_inner; + + using _InnerView = adjacent_view<_Vp, _Nm>; + + template + using _InnerIter = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using _InnerSent = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template class _Iterator; + template class _Sentinel; + + public: + adjacent_transform_view() = default; + + constexpr explicit + adjacent_transform_view(_Vp __base, _Fp __fun) + : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) + { } + + constexpr auto + begin() + { return _Iterator(*this, _M_inner.begin()); } + + constexpr auto + begin() const + requires range + && regular_invocable<__detail::__unarize, + range_reference_t> + { return _Iterator(*this, _M_inner.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator(*this, _M_inner.end()); + else + return _Sentinel(_M_inner.end()); + } + + constexpr auto + end() const + requires range + && regular_invocable<__detail::__unarize, + range_reference_t> + { + if constexpr (common_range) + return _Iterator(*this, _M_inner.end()); + else + return _Sentinel(_M_inner.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_inner.size(); } + + constexpr auto + size() const requires sized_range + { return _M_inner.size(); } + }; + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + template + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Iterator + { + using _Parent = __detail::__maybe_const_t<_Const, adjacent_transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + _Parent* _M_parent = nullptr; + _InnerIter<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, _InnerIter<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__unarize; + using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>, + range_reference_t<_Base>>; + using _Cat = typename iterator_traits>::iterator_category; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr (derived_from<_Cat, random_access_iterator_tag>) + return random_access_iterator_tag{}; + else if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend class adjacent_transform_view; + + public: + using iterator_category = decltype(_S_iter_cat()); + using iterator_concept = typename _InnerIter<_Const>::iterator_concept; + using value_type + = remove_cvref_t&, _Nm>, + range_reference_t<_Base>>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to<_InnerIter, _InnerIter<_Const>> + : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const requires random_access_range<_Base> + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, __iters[__n]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_inner == __y._M_inner; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner < __y._M_inner; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner > __y._M_inner; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner <= __y._M_inner; } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner >= __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> && + three_way_comparable<_InnerIter<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner - __n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<_InnerIter<_Const>, _InnerIter<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + template + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Sentinel + { + _InnerSent<_Const> _M_inner; + + constexpr explicit + _Sentinel(_InnerSent<_Const> __inner) + : _M_inner(__inner) + { } + + friend class adjacent_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to<_InnerSent, _InnerSent<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template + requires sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_adjacent_transform_view + = requires { adjacent_transform_view, decay_t<_Fp>, _Nm> + (std::declval<_Range>(), std::declval<_Fp>()); }; + } + + template + struct _AdjacentTransform : __adaptor::_RangeAdaptor<_AdjacentTransform<_Nm>> + { + template + requires (_Nm == 0) || __detail::__can_adjacent_transform_view<_Nm, _Range, _Fp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const + { + if constexpr (_Nm == 0) + return zip_transform(std::forward<_Fp>(__f)); + else + return adjacent_transform_view, decay_t<_Fp>, _Nm> + (std::forward<_Range>(__r), std::forward<_Fp>(__f)); + } + + using __adaptor::_RangeAdaptor<_AdjacentTransform>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + template + inline constexpr _AdjacentTransform<_Nm> adjacent_transform; + + inline constexpr auto pairwise_transform = adjacent_transform<2>; + } +#endif // __cpp_lib_ranges_zip + +#ifdef __cpp_lib_ranges_chunk // C++ >= 23 + namespace __detail + { + template + constexpr _Tp __div_ceil(_Tp __num, _Tp __denom) + { + _Tp __r = __num / __denom; + if (__num % __denom) + ++__r; + return __r; + } + } + + template + requires input_range<_Vp> + class chunk_view : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + range_difference_t<_Vp> _M_remainder = 0; + __detail::__non_propagating_cache> _M_current; + + class _OuterIter; + class _InnerIter; + + public: + constexpr explicit + chunk_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n >= 0); } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _OuterIter + begin() + { + _M_current = ranges::begin(_M_base); + _M_remainder = _M_n; + return _OuterIter(*this); + } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() requires sized_range<_Vp> + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + + constexpr auto + size() const requires sized_range + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + }; + + template + chunk_view(_Range&&, range_difference_t<_Range>) -> chunk_view>; + + template + requires input_range<_Vp> + class chunk_view<_Vp>::_OuterIter + { + chunk_view* _M_parent; + + constexpr explicit + _OuterIter(chunk_view& __parent) noexcept + : _M_parent(std::__addressof(__parent)) + { } + + friend chunk_view; + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t<_Vp>; + + struct value_type; + + _OuterIter(_OuterIter&&) = default; + _OuterIter& operator=(_OuterIter&&) = default; + + constexpr value_type + operator*() const + { + __glibcxx_assert(*this != default_sentinel); + return value_type(*_M_parent); + } + + constexpr _OuterIter& + operator++() + { + __glibcxx_assert(*this != default_sentinel); + ranges::advance(*_M_parent->_M_current, _M_parent->_M_remainder, + ranges::end(_M_parent->_M_base)); + _M_parent->_M_remainder = _M_parent->_M_n; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + friend constexpr bool + operator==(const _OuterIter& __x, default_sentinel_t) + { + return *__x._M_parent->_M_current == ranges::end(__x._M_parent->_M_base) + && __x._M_parent->_M_remainder != 0; + } + + friend constexpr difference_type + operator-(default_sentinel_t, const _OuterIter& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { + const auto __dist = ranges::end(__x._M_parent->_M_base) - *__x._M_parent->_M_current; + + if (__dist < __x._M_parent->_M_remainder) + return __dist == 0 ? 0 : 1; + + return 1 + __detail::__div_ceil(__dist - __x._M_parent->_M_remainder, + __x._M_parent->_M_n); + } + + friend constexpr difference_type + operator-(const _OuterIter& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return -(__y - __x); } + }; + + template + requires input_range<_Vp> + struct chunk_view<_Vp>::_OuterIter::value_type : view_interface + { + private: + chunk_view* _M_parent; + + constexpr explicit + value_type(chunk_view& __parent) noexcept + : _M_parent(std::__addressof(__parent)) + { } + + friend _OuterIter; + + public: + constexpr _InnerIter + begin() const noexcept + { return _InnerIter(*_M_parent); } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() const + requires sized_sentinel_for, iterator_t<_Vp>> + { + return __detail::__to_unsigned_like + (ranges::min(_M_parent->_M_remainder, + ranges::end(_M_parent->_M_base) - *_M_parent->_M_current)); + } + }; + + template + requires input_range<_Vp> + class chunk_view<_Vp>::_InnerIter + { + chunk_view* _M_parent; + + constexpr explicit + _InnerIter(chunk_view& __parent) noexcept + : _M_parent(std::__addressof(__parent)) + { } + + friend _OuterIter::value_type; + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t<_Vp>; + using value_type = range_value_t<_Vp>; + + _InnerIter(_InnerIter&&) = default; + _InnerIter& operator=(_InnerIter&&) = default; + + constexpr const iterator_t<_Vp>& + base() const & + { return *_M_parent->_M_current; } + + constexpr range_reference_t<_Vp> + operator*() const + { + __glibcxx_assert(*this != default_sentinel); + return **_M_parent->_M_current; + } + + constexpr _InnerIter& + operator++() + { + __glibcxx_assert(*this != default_sentinel); + ++*_M_parent->_M_current; + if (*_M_parent->_M_current == ranges::end(_M_parent->_M_base)) + _M_parent->_M_remainder = 0; + else + --_M_parent->_M_remainder; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + friend constexpr bool + operator==(const _InnerIter& __x, default_sentinel_t) noexcept + { return __x._M_parent->_M_remainder == 0; } + + friend constexpr difference_type + operator-(default_sentinel_t, const _InnerIter& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { + return ranges::min(__x._M_parent->_M_remainder, + ranges::end(__x._M_parent->_M_base) - *__x._M_parent->_M_current); + } + + friend constexpr difference_type + operator-(const _InnerIter& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return -(__y - __x); } + }; + + template + requires forward_range<_Vp> + class chunk_view<_Vp> : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + template class _Iterator; + + public: + constexpr explicit + chunk_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n > 0); } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(this, ranges::begin(_M_base)); } + + constexpr auto + begin() const requires forward_range + { return _Iterator(this, ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp> && sized_range<_Vp>) + { + auto __missing = (_M_n - ranges::distance(_M_base) % _M_n) % _M_n; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range<_Vp> && !bidirectional_range<_Vp>) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + end() const requires forward_range + { + if constexpr (common_range && sized_range) + { + auto __missing = (_M_n - ranges::distance(_M_base) % _M_n) % _M_n; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range && !bidirectional_range) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + size() requires sized_range<_Vp> + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + + constexpr auto + size() const requires sized_range + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + }; + + template + inline constexpr bool enable_borrowed_range> + = forward_range<_Vp> && enable_borrowed_range<_Vp>; + + template + requires forward_range<_Vp> + template + class chunk_view<_Vp>::_Iterator + { + using _Parent = __detail::__maybe_const_t<_Const, chunk_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + range_difference_t<_Base> _M_n = 0; + range_difference_t<_Base> _M_missing = 0; + + constexpr + _Iterator(_Parent* __parent, iterator_t<_Base> __current, + range_difference_t<_Base> __missing = 0) + : _M_current(__current), _M_end(ranges::end(__parent->_M_base)), + _M_n(__parent->_M_n), _M_missing(__missing) + { } + + static auto + _S_iter_cat() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend chunk_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_cat()); + using value_type = decltype(views::take(subrange(_M_current, _M_end), _M_n)); + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr _Iterator(_Iterator __i) + requires _Const + && convertible_to, iterator_t<_Base>> + && convertible_to, sentinel_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_end(std::move(__i._M_end)), + _M_n(__i._M_n), _M_missing(__i._M_missing) + { } + + constexpr iterator_t<_Base> + base() const + { return _M_current; } + + constexpr value_type + operator*() const + { + __glibcxx_assert(_M_current != _M_end); + return views::take(subrange(_M_current, _M_end), _M_n); + } + + constexpr _Iterator& + operator++() + { + __glibcxx_assert(_M_current != _M_end); + _M_missing = ranges::advance(_M_current, _M_n, _M_end); + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + ranges::advance(_M_current, _M_missing - _M_n); + _M_missing = 0; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + if (__x > 0) + { + __glibcxx_assert(ranges::distance(_M_current, _M_end) > _M_n * (__x - 1)); + _M_missing = ranges::advance(_M_current, _M_n * __x, _M_end); + } + else if (__x < 0) + { + ranges::advance(_M_current, _M_n * __x + _M_missing); + _M_missing = 0; + } + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { return *this += -__x; } + + constexpr value_type + operator[](difference_type __n) const + requires random_access_range<_Base> + { return *(*this + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { return __x._M_current == __x._M_end; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current > __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { + return (__x._M_current - __y._M_current + + __x._M_missing - __y._M_missing) / __x._M_n; + } + + friend constexpr difference_type + operator-(default_sentinel_t __y, const _Iterator& __x) + requires sized_sentinel_for, iterator_t<_Base>> + { return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return -(__y - __x); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_chunk_view + = requires { chunk_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } + + struct _Chunk : __adaptor::_RangeAdaptor<_Chunk> + { + template> + requires __detail::__can_chunk_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { return chunk_view(std::forward<_Range>(__r), __n); } + + using __adaptor::_RangeAdaptor<_Chunk>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Chunk chunk; + } +#endif // __cpp_lib_ranges_chunk + +#ifdef __cpp_lib_ranges_slide // C++ >= 23 + namespace __detail + { + template + concept __slide_caches_nothing = random_access_range<_Vp> && sized_range<_Vp>; + + template + concept __slide_caches_last + = !__slide_caches_nothing<_Vp> && bidirectional_range<_Vp> && common_range<_Vp>; + + template + concept __slide_caches_first + = !__slide_caches_nothing<_Vp> && !__slide_caches_last<_Vp>; + } + + template + requires view<_Vp> + class slide_view : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + [[no_unique_address]] + __detail::__maybe_present_t<__detail::__slide_caches_first<_Vp>, + __detail::_CachedPosition<_Vp>, 0> _M_cached_begin; + [[no_unique_address]] + __detail::__maybe_present_t<__detail::__slide_caches_last<_Vp>, + __detail::_CachedPosition<_Vp>, 1> _M_cached_end; + + template class _Iterator; + class _Sentinel; + + public: + constexpr explicit + slide_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n > 0); } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vp> + && __detail::__slide_caches_nothing)) + { + if constexpr (__detail::__slide_caches_first<_Vp>) + { + iterator_t<_Vp> __it; + if (_M_cached_begin._M_has_value()) + __it = _M_cached_begin._M_get(_M_base); + else + { + __it = ranges::next(ranges::begin(_M_base), _M_n - 1, ranges::end(_M_base)); + _M_cached_begin._M_set(_M_base, __it); + } + return _Iterator(ranges::begin(_M_base), std::move(__it), _M_n); + } + else + return _Iterator(ranges::begin(_M_base), _M_n); + } + + constexpr auto + begin() const requires __detail::__slide_caches_nothing + { return _Iterator(ranges::begin(_M_base), _M_n); } + + constexpr auto + end() requires (!(__detail::__simple_view<_Vp> + && __detail::__slide_caches_nothing)) + { + if constexpr (__detail::__slide_caches_nothing<_Vp>) + return _Iterator(ranges::begin(_M_base) + range_difference_t<_Vp>(size()), + _M_n); + else if constexpr (__detail::__slide_caches_last<_Vp>) + { + iterator_t<_Vp> __it; + if (_M_cached_end._M_has_value()) + __it = _M_cached_end._M_get(_M_base); + else + { + __it = ranges::prev(ranges::end(_M_base), _M_n - 1, ranges::begin(_M_base)); + _M_cached_end._M_set(_M_base, __it); + } + return _Iterator(std::move(__it), _M_n); + } + else if constexpr (common_range<_Vp>) + return _Iterator(ranges::end(_M_base), ranges::end(_M_base), _M_n); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires __detail::__slide_caches_nothing + { return begin() + range_difference_t(size()); } + + constexpr auto + size() requires sized_range<_Vp> + { + auto __sz = ranges::distance(_M_base) - _M_n + 1; + if (__sz < 0) + __sz = 0; + return __detail::__to_unsigned_like(__sz); + } + + constexpr auto + size() const requires sized_range + { + auto __sz = ranges::distance(_M_base) - _M_n + 1; + if (__sz < 0) + __sz = 0; + return __detail::__to_unsigned_like(__sz); + } + }; + + template + slide_view(_Range&&, range_difference_t<_Range>) -> slide_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Vp>; + + template + requires view<_Vp> + template + class slide_view<_Vp>::_Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + static constexpr bool _S_last_elt_present + = __detail::__slide_caches_first<_Base>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + [[no_unique_address]] + __detail::__maybe_present_t<_S_last_elt_present, iterator_t<_Base>> + _M_last_elt = decltype(_M_last_elt)(); + range_difference_t<_Base> _M_n = 0; + + constexpr + _Iterator(iterator_t<_Base> __current, range_difference_t<_Base> __n) + requires (!_S_last_elt_present) + : _M_current(__current), _M_n(__n) + { } + + constexpr + _Iterator(iterator_t<_Base> __current, iterator_t<_Base> __last_elt, + range_difference_t<_Base> __n) + requires _S_last_elt_present + : _M_current(__current), _M_last_elt(__last_elt), _M_n(__n) + { } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend slide_view; + friend slide_view::_Sentinel; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type = decltype(views::counted(_M_current, _M_n)); + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_n(__i._M_n) + { } + + constexpr auto + operator*() const + { return views::counted(_M_current, _M_n); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + if constexpr (_S_last_elt_present) + ++_M_last_elt; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + if constexpr (_S_last_elt_present) + --_M_last_elt; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + _M_current += __x; + if constexpr (_S_last_elt_present) + _M_last_elt += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { + _M_current -= __x; + if constexpr (_S_last_elt_present) + _M_last_elt -= __x; + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires random_access_range<_Base> + { return views::counted(_M_current + __n, _M_n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { + if constexpr (_S_last_elt_present) + return __x._M_last_elt == __y._M_last_elt; + else + return __x._M_current == __y._M_current; + } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { + if constexpr (_S_last_elt_present) + return __x._M_last_elt - __y._M_last_elt; + else + return __x._M_current - __y._M_current; + } + }; + + template + requires view<_Vp> + class slide_view<_Vp>::_Sentinel + { + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr explicit + _Sentinel(sentinel_t<_Vp> __end) + : _M_end(__end) + { } + + friend slide_view; + + public: + _Sentinel() = default; + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __x._M_last_elt == __y._M_end; } + + friend constexpr range_difference_t<_Vp> + operator-(const _Iterator& __x, const _Sentinel& __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return __x._M_last_elt - __y._M_end; } + + friend constexpr range_difference_t<_Vp> + operator-(const _Sentinel& __y, const _Iterator& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { return __y._M_end -__x._M_last_elt; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_slide_view + = requires { slide_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } + + struct _Slide : __adaptor::_RangeAdaptor<_Slide> + { + template> + requires __detail::__can_slide_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { return slide_view(std::forward<_Range>(__r), __n); } + + using __adaptor::_RangeAdaptor<_Slide>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Slide slide; + } +#endif // __cpp_lib_ranges_slide + +#ifdef __cpp_lib_ranges_chunk_by // C++ >= 23 + template, iterator_t<_Vp>> _Pred> + requires view<_Vp> && is_object_v<_Pred> + class chunk_by_view : public view_interface> + { + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + __detail::_CachedPosition<_Vp> _M_cached_begin; + + constexpr iterator_t<_Vp> + _M_find_next(iterator_t<_Vp> __current) + { + __glibcxx_assert(_M_pred.has_value()); + auto __pred = [this](_Tp&& __x, _Up&& __y) { + return !bool((*_M_pred)(std::forward<_Tp>(__x), std::forward<_Up>(__y))); + }; + auto __it = ranges::adjacent_find(__current, ranges::end(_M_base), __pred); + return ranges::next(__it, 1, ranges::end(_M_base)); + } + + constexpr iterator_t<_Vp> + _M_find_prev(iterator_t<_Vp> __current) requires bidirectional_range<_Vp> + { + __glibcxx_assert(_M_pred.has_value()); + auto __pred = [this](_Tp&& __x, _Up&& __y) { + return !bool((*_M_pred)(std::forward<_Up>(__y), std::forward<_Tp>(__x))); + }; + auto __rbegin = std::make_reverse_iterator(__current); + auto __rend = std::make_reverse_iterator(ranges::begin(_M_base)); + __glibcxx_assert(__rbegin != __rend); + auto __it = ranges::adjacent_find(__rbegin, __rend, __pred).base(); + return ranges::prev(__it, 1, ranges::begin(_M_base)); + } + + class _Iterator; + + public: + chunk_by_view() requires (default_initializable<_Vp> + && default_initializable<_Pred>) + = default; + + constexpr explicit + chunk_by_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr _Iterator + begin() + { + __glibcxx_assert(_M_pred.has_value()); + iterator_t<_Vp> __it; + if (_M_cached_begin._M_has_value()) + __it = _M_cached_begin._M_get(_M_base); + else + { + __it = _M_find_next(ranges::begin(_M_base)); + _M_cached_begin._M_set(_M_base, __it); + } + return _Iterator(*this, ranges::begin(_M_base), __it); + } + + constexpr auto + end() + { + if constexpr (common_range<_Vp>) + return _Iterator(*this, ranges::end(_M_base), ranges::end(_M_base)); + else + return default_sentinel; + } + }; + + template + chunk_by_view(_Range&&, _Pred) -> chunk_by_view, _Pred>; + + template, iterator_t<_Vp>> _Pred> + requires view<_Vp> && is_object_v<_Pred> + class chunk_by_view<_Vp, _Pred>::_Iterator + { + chunk_by_view* _M_parent = nullptr; + iterator_t<_Vp> _M_current = iterator_t<_Vp>(); + iterator_t<_Vp> _M_next = iterator_t<_Vp>(); + + constexpr + _Iterator(chunk_by_view& __parent, iterator_t<_Vp> __current, iterator_t<_Vp> __next) + : _M_parent(std::__addressof(__parent)), _M_current(__current), _M_next(__next) + { } + + static auto + _S_iter_concept() + { + if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend chunk_by_view; + + public: + using value_type = subrange>; + using difference_type = range_difference_t<_Vp>; + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + + _Iterator() = default; + + constexpr value_type + operator*() const + { + __glibcxx_assert(_M_current != _M_next); + return ranges::subrange(_M_current, _M_next); + } + + constexpr _Iterator& + operator++() + { + __glibcxx_assert(_M_current != _M_next); + _M_current = _M_next; + _M_next = _M_parent->_M_find_next(_M_current); + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Vp> + { + _M_next = _M_current; + _M_current = _M_parent->_M_find_prev(_M_next); + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Vp> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { return __x._M_current == __x._M_next; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_chunk_by_view + = requires { chunk_by_view(std::declval<_Range>(), std::declval<_Pred>()); }; + } + + struct _ChunkBy : __adaptor::_RangeAdaptor<_ChunkBy> + { + template + requires __detail::__can_chunk_by_view<_Range, _Pred> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pred&& __pred) const + { return chunk_by_view(std::forward<_Range>(__r), std::forward<_Pred>(__pred)); } + + using __adaptor::_RangeAdaptor<_ChunkBy>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _ChunkBy chunk_by; + } +#endif // __cpp_lib_ranges_chunk_by + +#ifdef __cpp_lib_ranges_join_with // C++ >= 23 + namespace __detail + { + template + concept __compatible_joinable_ranges + = common_with, range_value_t<_Pattern>> + && common_reference_with, + range_reference_t<_Pattern>> + && common_reference_with, + range_rvalue_reference_t<_Pattern>>; + + template + concept __bidirectional_common = bidirectional_range<_Range> && common_range<_Range>; + } + + template + requires view<_Vp> && view<_Pattern> + && input_range> + && __detail::__compatible_joinable_ranges, _Pattern> + class join_with_view : public view_interface> + { + using _InnerRange = range_reference_t<_Vp>; + + _Vp _M_base = _Vp(); + [[no_unique_address]] + __detail::__maybe_present_t, + __detail::__non_propagating_cache>> _M_outer_it; + __detail::__non_propagating_cache> _M_inner; + _Pattern _M_pattern = _Pattern(); + + template using _Base = __detail::__maybe_const_t<_Const, _Vp>; + template using _InnerBase = range_reference_t<_Base<_Const>>; + template using _PatternBase = __detail::__maybe_const_t<_Const, _Pattern>; + + template using _OuterIter = iterator_t<_Base<_Const>>; + template using _InnerIter = iterator_t<_InnerBase<_Const>>; + template using _PatternIter = iterator_t<_PatternBase<_Const>>; + + template + static constexpr bool _S_ref_is_glvalue = is_reference_v<_InnerBase<_Const>>; + + template + struct __iter_cat + { }; + + template + requires _S_ref_is_glvalue<_Const> + && forward_range<_Base<_Const>> + && forward_range<_InnerBase<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using _OuterIter = join_with_view::_OuterIter<_Const>; + using _InnerIter = join_with_view::_InnerIter<_Const>; + using _PatternIter = join_with_view::_PatternIter<_Const>; + using _OuterCat = typename iterator_traits<_OuterIter>::iterator_category; + using _InnerCat = typename iterator_traits<_InnerIter>::iterator_category; + using _PatternCat = typename iterator_traits<_PatternIter>::iterator_category; + if constexpr (!is_lvalue_reference_v, + iter_reference_t<_PatternIter>>>) + return input_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag> + && derived_from<_InnerCat, bidirectional_iterator_tag> + && derived_from<_PatternCat, bidirectional_iterator_tag> + && common_range<_InnerBase<_Const>> + && common_range<_PatternBase<_Const>>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, forward_iterator_tag> + && derived_from<_InnerCat, forward_iterator_tag> + && derived_from<_PatternCat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template struct _Iterator; + template struct _Sentinel; + + public: + join_with_view() requires (default_initializable<_Vp> + && default_initializable<_Pattern>) + = default; + + constexpr + join_with_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view>> + constexpr + join_with_view(_Range&& __r, range_value_t<_InnerRange> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (forward_range<_Vp>) + { + constexpr bool __use_const = is_reference_v<_InnerRange> + && __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _Iterator<__use_const>{*this, ranges::begin(_M_base)}; + } + else + { + _M_outer_it = ranges::begin(_M_base); + return _Iterator{*this}; + } + } + + constexpr auto + begin() const + requires forward_range + && forward_range + && is_reference_v> + && input_range> + { return _Iterator{*this, ranges::begin(_M_base)}; } + + constexpr auto + end() + { + constexpr bool __use_const + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + if constexpr (is_reference_v<_InnerRange> + && forward_range<_Vp> && common_range<_Vp> + && forward_range<_InnerRange> && common_range<_InnerRange>) + return _Iterator<__use_const>{*this, ranges::end(_M_base)}; + else + return _Sentinel<__use_const>{*this}; + } + + constexpr auto + end() const + requires forward_range + && forward_range + && is_reference_v> + && input_range> + { + using _InnerConstRange = range_reference_t; + if constexpr (forward_range<_InnerConstRange> + && common_range + && common_range<_InnerConstRange>) + return _Iterator{*this, ranges::end(_M_base)}; + else + return _Sentinel{*this}; + } + }; + + template + join_with_view(_Range&&, _Pattern&&) + -> join_with_view, views::all_t<_Pattern>>; + + template + join_with_view(_Range&&, range_value_t>) + -> join_with_view, + single_view>>>; + + template + requires view<_Vp> && view<_Pattern> + && input_range> + && __detail::__compatible_joinable_ranges, _Pattern> + template + class join_with_view<_Vp, _Pattern>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, join_with_view>; + using _Base = join_with_view::_Base<_Const>; + using _InnerBase = join_with_view::_InnerBase<_Const>; + using _PatternBase = join_with_view::_PatternBase<_Const>; + + using _OuterIter = join_with_view::_OuterIter<_Const>; + using _InnerIter = join_with_view::_InnerIter<_Const>; + using _PatternIter = join_with_view::_PatternIter<_Const>; + + static constexpr bool _S_ref_is_glvalue = join_with_view::_S_ref_is_glvalue<_Const>; + + _Parent* _M_parent = nullptr; + [[no_unique_address]] + __detail::__maybe_present_t, _OuterIter> _M_outer_it; + variant<_PatternIter, _InnerIter> _M_inner_it; + + constexpr _OuterIter& + _M_get_outer() + { + if constexpr (forward_range<_Base>) + return _M_outer_it; + else + return *_M_parent->_M_outer_it; + } + + constexpr const _OuterIter& + _M_get_outer() const + { + if constexpr (forward_range<_Base>) + return _M_outer_it; + else + return *_M_parent->_M_outer_it; + } + + constexpr + _Iterator(_Parent& __parent, _OuterIter __outer) + requires forward_range<_Base> + : _M_parent(std::__addressof(__parent)), _M_outer_it(std::move(__outer)) + { + if (_M_get_outer() != ranges::end(_M_parent->_M_base)) + { + auto&& __inner = _M_update_inner(); + _M_inner_it.template emplace<1>(ranges::begin(__inner)); + _M_satisfy(); + } + } + + constexpr + _Iterator(_Parent& __parent) + requires (!forward_range<_Base>) + : _M_parent(std::__addressof(__parent)) + { + if (_M_get_outer() != ranges::end(_M_parent->_M_base)) + { + auto&& __inner = _M_update_inner(); + _M_inner_it.template emplace<1>(ranges::begin(__inner)); + _M_satisfy(); + } + } + + constexpr auto& + _M_update_inner() + { + _OuterIter& __outer = _M_get_outer(); + if constexpr (_S_ref_is_glvalue) + return __detail::__as_lvalue(*__outer); + else + return _M_parent->_M_inner._M_emplace_deref(__outer); + } + + constexpr auto& + _M_get_inner() + { + if constexpr (_S_ref_is_glvalue) + return __detail::__as_lvalue(*_M_get_outer()); + else + return *_M_parent->_M_inner; + } + + constexpr void + _M_satisfy() + { + while (true) + { + if (_M_inner_it.index() == 0) + { + if (std::get<0>(_M_inner_it) != ranges::end(_M_parent->_M_pattern)) + break; + + auto&& __inner = _M_update_inner(); + _M_inner_it.template emplace<1>(ranges::begin(__inner)); + } + else + { + auto&& __inner = _M_get_inner(); + if (std::get<1>(_M_inner_it) != ranges::end(__inner)) + break; + + if (++_M_get_outer() == ranges::end(_M_parent->_M_base)) + { + if constexpr (_S_ref_is_glvalue) + _M_inner_it.template emplace<0>(); + break; + } + + _M_inner_it.template emplace<0>(ranges::begin(_M_parent->_M_pattern)); + } + } + } + + static auto + _S_iter_concept() + { + if constexpr (_S_ref_is_glvalue + && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && forward_range<_Base> + && forward_range<_InnerBase>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend join_with_view; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in join_with_view::__iter_cat + using value_type = common_type_t, + iter_value_t<_PatternIter>>; + using difference_type = common_type_t, + iter_difference_t<_InnerIter>, + iter_difference_t<_PatternIter>>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _OuterIter> + && convertible_to, _InnerIter> + && convertible_to, _PatternIter> + : _M_parent(__i._M_parent), + _M_outer_it(std::move(__i._M_outer_it)) + { + if (__i._M_inner_it.index() == 0) + _M_inner_it.template emplace<0>(std::get<0>(std::move(__i._M_inner_it))); + else + _M_inner_it.template emplace<1>(std::get<1>(std::move(__i._M_inner_it))); + } + + constexpr common_reference_t, + iter_reference_t<_PatternIter>> + operator*() const + { + if (_M_inner_it.index() == 0) + return *std::get<0>(_M_inner_it); + else + return *std::get<1>(_M_inner_it); + } + + constexpr _Iterator& + operator++() + { + if (_M_inner_it.index() == 0) + ++std::get<0>(_M_inner_it); + else + ++std::get<1>(_M_inner_it); + _M_satisfy(); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires _S_ref_is_glvalue + && forward_iterator<_OuterIter> && forward_iterator<_InnerIter> + { + _Iterator __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires _S_ref_is_glvalue + && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase> + { + if (_M_outer_it == ranges::end(_M_parent->_M_base)) + { + auto&& __inner = *--_M_outer_it; + _M_inner_it.template emplace<1>(ranges::end(__inner)); + } + + while (true) + { + if (_M_inner_it.index() == 0) + { + auto& __it = std::get<0>(_M_inner_it); + if (__it == ranges::begin(_M_parent->_M_pattern)) + { + auto&& __inner = *--_M_outer_it; + _M_inner_it.template emplace<1>(ranges::end(__inner)); + } + else + break; + } + else + { + auto& __it = std::get<1>(_M_inner_it); + auto&& __inner = *_M_outer_it; + if (__it == ranges::begin(__inner)) + _M_inner_it.template emplace<0>(ranges::end(_M_parent->_M_pattern)); + else + break; + } + } + + if (_M_inner_it.index() == 0) + --std::get<0>(_M_inner_it); + else + --std::get<1>(_M_inner_it); + return *this; + } + + constexpr _Iterator + operator--(int) + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase> + { + _Iterator __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires _S_ref_is_glvalue + && forward_range<_Base> && equality_comparable<_InnerIter> + { return __x._M_outer_it == __y._M_outer_it && __x._M_inner_it ==__y._M_inner_it; } + + friend constexpr common_reference_t, + iter_rvalue_reference_t<_PatternIter>> + iter_move(const _Iterator& __x) + { + if (__x._M_inner_it.index() == 0) + return ranges::iter_move(std::get<0>(__x._M_inner_it)); + else + return ranges::iter_move(std::get<1>(__x._M_inner_it)); + } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + requires indirectly_swappable<_InnerIter, _PatternIter> + { + if (__x._M_inner_it.index() == 0) + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + else + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + } + }; + + template + requires view<_Vp> && view<_Pattern> + && input_range> + && __detail::__compatible_joinable_ranges, _Pattern> + template + class join_with_view<_Vp, _Pattern>::_Sentinel + { + using _Parent = __detail::__maybe_const_t<_Const, join_with_view>; + using _Base = join_with_view::_Base<_Const>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(_Parent& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + friend join_with_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_get_outer() == __y._M_end; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_join_with_view + = requires { join_with_view(std::declval<_Range>(), std::declval<_Pattern>()); }; + } // namespace __detail + + struct _JoinWith : __adaptor::_RangeAdaptor<_JoinWith> + { + template + requires __detail::__can_join_with_view<_Range, _Pattern> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const + { + return join_with_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); + } + + using _RangeAdaptor<_JoinWith>::operator(); + static constexpr int _S_arity = 2; + template + static constexpr bool _S_has_simple_extra_args + = _LazySplit::_S_has_simple_extra_args<_Pattern>; + }; + + inline constexpr _JoinWith join_with; + } // namespace views +#endif // __cpp_lib_ranges_join_with + +#ifdef __cpp_lib_ranges_repeat // C++ >= 23 + template + requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> + && (__detail::__is_integer_like<_Bound> || same_as<_Bound, unreachable_sentinel_t>) + class repeat_view : public view_interface> + { + __detail::__box<_Tp> _M_value; + [[no_unique_address]] _Bound _M_bound = _Bound(); + + struct _Iterator; + + template + friend constexpr auto + views::__detail::__take_of_repeat_view(_Range&&, range_difference_t<_Range>); + + template + friend constexpr auto + views::__detail::__drop_of_repeat_view(_Range&&, range_difference_t<_Range>); + + public: + repeat_view() requires default_initializable<_Tp> = default; + + constexpr explicit + repeat_view(const _Tp& __value, _Bound __bound = _Bound()) + requires copy_constructible<_Tp> + : _M_value(__value), _M_bound(__bound) + { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + __glibcxx_assert(__bound >= 0); + } + + constexpr explicit + repeat_view(_Tp&& __value, _Bound __bound = _Bound()) + : _M_value(std::move(__value)), _M_bound(__bound) + { } + + template + requires constructible_from<_Tp, _Args...> + && constructible_from<_Bound, _BoundArgs...> + constexpr explicit + repeat_view(piecewise_construct_t, + tuple<_Args...> __args, + tuple<_BoundArgs...> __bound_args = tuple<>{}) + : _M_value(std::make_from_tuple<_Tp>(std::move(__args))), + _M_bound(std::make_from_tuple<_Bound>(std::move(__bound_args))) + { } + + constexpr _Iterator + begin() const + { return _Iterator(std::__addressof(*_M_value)); } + + constexpr _Iterator + end() const requires (!same_as<_Bound, unreachable_sentinel_t>) + { return _Iterator(std::__addressof(*_M_value), _M_bound); } + + constexpr unreachable_sentinel_t + end() const noexcept + { return unreachable_sentinel; } + + constexpr auto + size() const requires (!same_as<_Bound, unreachable_sentinel_t>) + { return __detail::__to_unsigned_like(_M_bound); } + }; + + template + repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + + template + requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> + && (__detail::__is_integer_like<_Bound> || same_as<_Bound, unreachable_sentinel_t>) + class repeat_view<_Tp, _Bound>::_Iterator + { + using __index_type + = __conditional_t, ptrdiff_t, _Bound>; + + const _Tp* _M_value = nullptr; + __index_type _M_current = __index_type(); + + constexpr explicit + _Iterator(const _Tp* __value, __index_type __bound = __index_type()) + : _M_value(__value), _M_current(__bound) + { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + __glibcxx_assert(__bound >= 0); + } + + friend repeat_view; + + public: + using iterator_concept = random_access_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = _Tp; + using difference_type = __conditional_t<__detail::__is_signed_integer_like<__index_type>, + __index_type, + __detail::__iota_diff_t<__index_type>>; + + _Iterator() = default; + + constexpr const _Tp& + operator*() const noexcept + { return *_M_value; } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + __glibcxx_assert(_M_current > 0); + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) + { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + __glibcxx_assert(_M_current + __n >= 0); + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) + { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + __glibcxx_assert(_M_current - __n >= 0); + _M_current -= __n; + return *this; + } + + constexpr const _Tp& + operator[](difference_type __n) const noexcept + { return *(*this + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current == __y._M_current; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + { + __i += __n; + return __i; + } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + { return __i + __n; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + { + __i -= __n; + return __i; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + { + return (static_cast(__x._M_current) + - static_cast(__y._M_current)); + } + }; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_repeat_view> = true; + + template + concept __can_repeat_view + = requires { repeat_view(std::declval<_Tp>()); }; + + template + concept __can_bounded_repeat_view + = requires { repeat_view(std::declval<_Tp>(), std::declval<_Bound>()); }; + } + + struct _Repeat + { + template + requires __detail::__can_repeat_view<_Tp> + constexpr auto + operator() [[nodiscard]] (_Tp&& __value) const + { return repeat_view(std::forward<_Tp>(__value)); } + + template + requires __detail::__can_bounded_repeat_view<_Tp, _Bound> + constexpr auto + operator() [[nodiscard]] (_Tp&& __value, _Bound __bound) const + { return repeat_view(std::forward<_Tp>(__value), __bound); } + }; + + inline constexpr _Repeat repeat; + + namespace __detail + { + template + constexpr auto + __take_of_repeat_view(_Range&& __r, range_difference_t<_Range> __n) + { + using _Tp = remove_cvref_t<_Range>; + static_assert(__is_repeat_view<_Tp>); + if constexpr (sized_range<_Tp>) + return views::repeat(*std::forward<_Range>(__r)._M_value, + std::min(ranges::distance(__r), __n)); + else + return views::repeat(*std::forward<_Range>(__r)._M_value, __n); + } + + template + constexpr auto + __drop_of_repeat_view(_Range&& __r, range_difference_t<_Range> __n) + { + using _Tp = remove_cvref_t<_Range>; + static_assert(__is_repeat_view<_Tp>); + if constexpr (sized_range<_Tp>) + { + auto __sz = ranges::distance(__r); + return views::repeat(*std::forward<_Range>(__r)._M_value, + __sz - std::min(__sz, __n)); + } + else + return __r; + } + } + } +#endif // __cpp_lib_ranges_repeat + +#ifdef __cpp_lib_ranges_stride // C++ >= 23 + template + requires view<_Vp> + class stride_view : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_stride; + + template using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + struct __iter_cat + { }; + + template + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using _Cat = typename iterator_traits>>::iterator_category; + if constexpr (derived_from<_Cat, random_access_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template class _Iterator; + + public: + constexpr explicit + stride_view(_Vp __base, range_difference_t<_Vp> __stride) + : _M_base(std::move(__base)), _M_stride(__stride) + { __glibcxx_assert(__stride > 0); } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr range_difference_t<_Vp> + stride() const noexcept + { return _M_stride; } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(this, ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(this, ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp> && sized_range<_Vp> && forward_range<_Vp>) + { + auto __missing = (_M_stride - ranges::distance(_M_base) % _M_stride) % _M_stride; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range<_Vp> && !bidirectional_range<_Vp>) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + end() const requires range + { + if constexpr (common_range && sized_range + && forward_range) + { + auto __missing = (_M_stride - ranges::distance(_M_base) % _M_stride) % _M_stride; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range && !bidirectional_range) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + size() requires sized_range<_Vp> + { + return __detail::__to_unsigned_like + (__detail::__div_ceil(ranges::distance(_M_base), _M_stride)); + } + + constexpr auto + size() const requires sized_range + { + return __detail::__to_unsigned_like + (__detail::__div_ceil(ranges::distance(_M_base), _M_stride)); + } + }; + + template + stride_view(_Range&&, range_difference_t<_Range>) -> stride_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Vp>; + + template + requires view<_Vp> + template + class stride_view<_Vp>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, stride_view>; + using _Base = stride_view::_Base<_Const>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + range_difference_t<_Base> _M_stride = 0; + range_difference_t<_Base> _M_missing = 0; + + constexpr + _Iterator(_Parent* __parent, iterator_t<_Base> __current, + range_difference_t<_Base> __missing = 0) + : _M_current(std::move(__current)), _M_end(ranges::end(__parent->_M_base)), + _M_stride(__parent->_M_stride), _M_missing(__missing) + { } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Base>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend stride_view; + + public: + using difference_type = range_difference_t<_Base>; + using value_type = range_value_t<_Base>; + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in stride_view::__iter_cat + + _Iterator() requires default_initializable> = default; + + constexpr + _Iterator(_Iterator __other) + requires _Const + && convertible_to, iterator_t<_Base>> + && convertible_to, sentinel_t<_Base>> + : _M_current(std::move(__other._M_current)), _M_end(std::move(__other._M_end)), + _M_stride(__other._M_stride), _M_missing(__other._M_missing) + { } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr const iterator_t<_Base>& + base() const & noexcept + { return _M_current; } + + constexpr decltype(auto) + operator*() const + { return *_M_current; } + + constexpr _Iterator& + operator++() + { + __glibcxx_assert(_M_current != _M_end); + _M_missing = ranges::advance(_M_current, _M_stride, _M_end); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + ranges::advance(_M_current, _M_missing - _M_stride); + _M_missing = 0; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + if (__n > 0) + { + __glibcxx_assert(ranges::distance(_M_current, _M_end) > _M_stride * (__n - 1)); + _M_missing = ranges::advance(_M_current, _M_stride * __n, _M_end); + } + else if (__n < 0) + { + ranges::advance(_M_current, _M_stride * __n + _M_missing); + _M_missing = 0; + } + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { return *this += -__n; } + + constexpr decltype(auto) operator[](difference_type __n) const + requires random_access_range<_Base> + { return *(*this + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { return __x._M_current == __x._M_end; } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y._M_current < __x._M_current; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y._M_current < __x._M_current); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x._M_current < __y._M_current); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> && three_way_comparable> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { return __i + __n; } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { + auto __n = __x._M_current - __y._M_current; + if constexpr (forward_range<_Base>) + return (__n + __x._M_missing - __y._M_missing) / __x._M_stride; + else if (__n < 0) + return -__detail::__div_ceil(-__n, __x._M_stride); + else + return __detail::__div_ceil(__n, __x._M_stride); + } + + friend constexpr difference_type + operator-(default_sentinel_t __y, const _Iterator& __x) + requires sized_sentinel_for, iterator_t<_Base>> + { return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_stride); } + + friend constexpr difference_type + operator-(const _Iterator& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return -(__y - __x); } + + friend constexpr range_rvalue_reference_t<_Base> + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable> + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_stride_view + = requires { stride_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } + + struct _Stride : __adaptor::_RangeAdaptor<_Stride> + { + template> + requires __detail::__can_stride_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { return stride_view(std::forward<_Range>(__r), __n); } + + using __adaptor::_RangeAdaptor<_Stride>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Stride stride; + } +#endif // __cpp_lib_ranges_stride + +#ifdef __cpp_lib_ranges_cartesian_product // C++ >= 23 + namespace __detail + { + template + concept __cartesian_product_is_random_access + = (random_access_range<__maybe_const_t<_Const, _First>> + && ... + && (random_access_range<__maybe_const_t<_Const, _Vs>> + && sized_range<__maybe_const_t<_Const, _Vs>>)); + + template + concept __cartesian_product_common_arg + = common_range<_Range> || (sized_range<_Range> && random_access_range<_Range>); + + template + concept __cartesian_product_is_bidirectional + = (bidirectional_range<__maybe_const_t<_Const, _First>> + && ... + && (bidirectional_range<__maybe_const_t<_Const, _Vs>> + && __cartesian_product_common_arg<__maybe_const_t<_Const, _Vs>>)); + + template + concept __cartesian_product_is_common = __cartesian_product_common_arg<_First>; + + template + concept __cartesian_product_is_sized = (sized_range<_Vs> && ...); + + template class FirstSent, typename _First, typename... _Vs> + concept __cartesian_is_sized_sentinel + = (sized_sentinel_for>, + iterator_t<__maybe_const_t<_Const, _First>>> + && ... + && (sized_range<__maybe_const_t<_Const, _Vs>> + && sized_sentinel_for>, + iterator_t<__maybe_const_t<_Const, _Vs>>>)); + + template<__cartesian_product_common_arg _Range> + constexpr auto + __cartesian_common_arg_end(_Range& __r) + { + if constexpr (common_range<_Range>) + return ranges::end(__r); + else + return ranges::begin(__r) + ranges::distance(__r); + } + } // namespace __detail + + template + requires (view<_First> && ... && view<_Vs>) + class cartesian_product_view : public view_interface> + { + tuple<_First, _Vs...> _M_bases; + + template class _Iterator; + + static auto + _S_difference_type() + { + // TODO: Implement the recommended practice of using the smallest + // sufficiently wide type according to the maximum sizes of the + // underlying ranges? + return common_type_t, + range_difference_t<_Vs>...>{}; + } + + public: + cartesian_product_view() = default; + + constexpr explicit + cartesian_product_view(_First __first, _Vs... __rest) + : _M_bases(std::move(__first), std::move(__rest)...) + { } + + constexpr _Iterator + begin() requires (!__detail::__simple_view<_First> || ... || !__detail::__simple_view<_Vs>) + { return _Iterator(*this, __detail::__tuple_transform(ranges::begin, _M_bases)); } + + constexpr _Iterator + begin() const requires (range && ... && range) + { return _Iterator(*this, __detail::__tuple_transform(ranges::begin, _M_bases)); } + + constexpr _Iterator + end() requires ((!__detail::__simple_view<_First> || ... || !__detail::__simple_view<_Vs>) + && __detail::__cartesian_product_is_common<_First, _Vs...>) + { + auto __its = [this](index_sequence<_Is...>) { + using _Ret = tuple, iterator_t<_Vs>...>; + bool __empty_tail = (ranges::empty(std::get<1 + _Is>(_M_bases)) || ...); + auto& __first = std::get<0>(_M_bases); + return _Ret{(__empty_tail + ? ranges::begin(__first) + : __detail::__cartesian_common_arg_end(__first)), + ranges::begin(std::get<1 + _Is>(_M_bases))...}; + }(make_index_sequence{}); + + return _Iterator{*this, std::move(__its)}; + } + + constexpr _Iterator + end() const requires __detail::__cartesian_product_is_common + { + auto __its = [this](index_sequence<_Is...>) { + using _Ret = tuple, iterator_t...>; + bool __empty_tail = (ranges::empty(std::get<1 + _Is>(_M_bases)) || ...); + auto& __first = std::get<0>(_M_bases); + return _Ret{(__empty_tail + ? ranges::begin(__first) + : __detail::__cartesian_common_arg_end(__first)), + ranges::begin(std::get<1 + _Is>(_M_bases))...}; + }(make_index_sequence{}); + + return _Iterator{*this, std::move(__its)}; + } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() requires __detail::__cartesian_product_is_sized<_First, _Vs...> + { + using _ST = __detail::__make_unsigned_like_t; + return [&](index_sequence<_Is...>) { + auto __size = static_cast<_ST>(1); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<_ST>) + { + bool __overflow + = (__builtin_mul_overflow(__size, + static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))), + &__size) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __size = (static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))) * ...); + return __size; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + constexpr auto + size() const requires __detail::__cartesian_product_is_sized + { + using _ST = __detail::__make_unsigned_like_t; + return [&](index_sequence<_Is...>) { + auto __size = static_cast<_ST>(1); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<_ST>) + { + bool __overflow + = (__builtin_mul_overflow(__size, + static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))), + &__size) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __size = (static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))) * ...); + return __size; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + }; + + template + cartesian_product_view(_Vs&&...) -> cartesian_product_view...>; + + template + requires (view<_First> && ... && view<_Vs>) + template + class cartesian_product_view<_First, _Vs...>::_Iterator + { + using _Parent = __maybe_const_t<_Const, cartesian_product_view>; + _Parent* _M_parent = nullptr; + tuple>, + iterator_t<__maybe_const_t<_Const, _Vs>>...> _M_current; + + constexpr + _Iterator(_Parent& __parent, decltype(_M_current) __current) + : _M_parent(std::__addressof(__parent)), + _M_current(std::move(__current)) + { } + + static auto + _S_iter_concept() + { + if constexpr (__detail::__cartesian_product_is_random_access<_Const, _First, _Vs...>) + return random_access_iterator_tag{}; + else if constexpr (__detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<__maybe_const_t<_Const, _First>>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend cartesian_product_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type + = tuple>, + range_value_t<__maybe_const_t<_Const, _Vs>>...>; + using reference + = tuple>, + range_reference_t<__maybe_const_t<_Const, _Vs>>...>; + using difference_type = decltype(cartesian_product_view::_S_difference_type()); + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const + && (convertible_to, iterator_t> + && ... && convertible_to, iterator_t>) + : _M_parent(std::__addressof(__i._M_parent)), + _M_current(std::move(__i._M_current)) + { } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { + return *__i; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + _M_next(); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<__maybe_const_t<_Const, _First>> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires __detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...> + { + _M_prev(); + return *this; + } + + constexpr _Iterator + operator--(int) + requires __detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { + _M_advance(__x); + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return *this += -__x; } + + constexpr reference + operator[](difference_type __n) const + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return *((*this) + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable>> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { + return [&](index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) + == ranges::end(std::get<_Is>(__x._M_parent->_M_bases))) + || ...); + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _First, _Vs...> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(_Iterator __x, difference_type __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __x += __y; } + + friend constexpr _Iterator + operator+(difference_type __x, _Iterator __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __y += __x; } + + friend constexpr _Iterator + operator-(_Iterator __x, difference_type __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __x -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires __detail::__cartesian_is_sized_sentinel<_Const, iterator_t, _First, _Vs...> + { return __x._M_distance_from(__y._M_current); } + + friend constexpr difference_type + operator-(const _Iterator& __i, default_sentinel_t) + requires __detail::__cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Vs...> + { + tuple __end_tuple = [&](index_sequence<_Is...>) { + return tuple{ranges::end(std::get<0>(__i._M_parent->_M_bases)), + ranges::begin(std::get<1 + _Is>(__i._M_parent->_M_bases))...}; + }(make_index_sequence{}); + return __i._M_distance_from(__end_tuple); + } + + friend constexpr difference_type + operator-(default_sentinel_t, const _Iterator& __i) + requires __detail::__cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Vs...> + { return -(__i - default_sentinel); } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires (indirectly_swappable>> + && ... + && indirectly_swappable>>) + { + [&](index_sequence<_Is...>) { + (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...); + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + private: + template + constexpr void + _M_next() + { + auto& __it = std::get<_Nm>(_M_current); + ++__it; + if constexpr (_Nm > 0) + if (__it == ranges::end(std::get<_Nm>(_M_parent->_M_bases))) + { + __it = ranges::begin(std::get<_Nm>(_M_parent->_M_bases)); + _M_next<_Nm - 1>(); + } + } + + template + constexpr void + _M_prev() + { + auto& __it = std::get<_Nm>(_M_current); + if constexpr (_Nm > 0) + if (__it == ranges::begin(std::get<_Nm>(_M_parent->_M_bases))) + { + __it = __detail::__cartesian_common_arg_end(std::get<_Nm>(_M_parent->_M_bases)); + _M_prev<_Nm - 1>(); + } + --__it; + } + + template + constexpr void + _M_advance(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { + if (__x == 1) + _M_next<_Nm>(); + else if (__x == -1) + _M_prev<_Nm>(); + else if (__x != 0) + { + // Constant time iterator advancement. + auto& __r = std::get<_Nm>(_M_parent->_M_bases); + auto& __it = std::get<_Nm>(_M_current); + if constexpr (_Nm == 0) + { +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (sized_range<__maybe_const_t<_Const, _First>>) + { + auto __size = ranges::ssize(__r); + auto __begin = ranges::begin(__r); + auto __offset = __it - __begin; + __glibcxx_assert(__offset + __x >= 0 && __offset + __x <= __size); + } +#endif + __it += __x; + } + else + { + auto __size = ranges::ssize(__r); + auto __begin = ranges::begin(__r); + auto __offset = __it - __begin; + __offset += __x; + __x = __offset / __size; + __offset %= __size; + if (__offset < 0) + { + __offset = __size + __offset; + --__x; + } + __it = __begin + __offset; + _M_advance<_Nm - 1>(__x); + } + } + } + + template + constexpr difference_type + _M_distance_from(const _Tuple& __t) const + { + return [&](index_sequence<_Is...>) { + auto __sum = static_cast(0); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral) + { + bool __overflow + = (__builtin_add_overflow(__sum, _M_scaled_distance<_Is>(__t), &__sum) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __sum = (_M_scaled_distance<_Is>(__t) + ...); + return __sum; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + template + constexpr difference_type + _M_scaled_distance(const _Tuple& __t) const + { + auto __dist = static_cast(std::get<_Nm>(_M_current) + - std::get<_Nm>(__t)); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral) + { + bool __overflow = __builtin_mul_overflow(__dist, _M_scaled_size<_Nm+1>(), &__dist); + __glibcxx_assert(!__overflow); + } + else +#endif + __dist *= _M_scaled_size<_Nm+1>(); + return __dist; + } + + template + constexpr difference_type + _M_scaled_size() const + { + if constexpr (_Nm <= sizeof...(_Vs)) + { + auto __size = static_cast(ranges::size + (std::get<_Nm>(_M_parent->_M_bases))); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral) + { + bool __overflow = __builtin_mul_overflow(__size, _M_scaled_size<_Nm+1>(), &__size); + __glibcxx_assert(!__overflow); + } + else +#endif + __size *= _M_scaled_size<_Nm+1>(); + return __size; + } + else + return static_cast(1); + } + }; + + namespace views + { + namespace __detail + { + template + concept __can_cartesian_product_view + = requires { cartesian_product_view...>(std::declval<_Ts>()...); }; + } + + struct _CartesianProduct + { + template + requires (sizeof...(_Ts) == 0 || __detail::__can_cartesian_product_view<_Ts...>) + constexpr auto + operator() [[nodiscard]] (_Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::single(tuple{}); + else + return cartesian_product_view...>(std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _CartesianProduct cartesian_product; + } +#endif // __cpp_lib_ranges_cartesian_product + +#ifdef __cpp_lib_ranges_as_rvalue // C++ >= 23 + template + requires view<_Vp> + class as_rvalue_view : public view_interface> + { + _Vp _M_base = _Vp(); + + public: + as_rvalue_view() requires default_initializable<_Vp> = default; + + constexpr explicit + as_rvalue_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return move_iterator(ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range + { return move_iterator(ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp>) + return move_iterator(ranges::end(_M_base)); + else + return move_sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (common_range) + return move_iterator(ranges::end(_M_base)); + else + return move_sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + as_rvalue_view(_Range&&) -> as_rvalue_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + concept __can_as_rvalue_view = requires { as_rvalue_view(std::declval<_Tp>()); }; + } + + struct _AsRvalue : __adaptor::_RangeAdaptorClosure<_AsRvalue> + { + template + requires __detail::__can_as_rvalue_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (same_as, + range_reference_t<_Range>>) + return views::all(std::forward<_Range>(__r)); + else + return as_rvalue_view(std::forward<_Range>(__r)); + } + }; + + inline constexpr _AsRvalue as_rvalue; + } +#endif // __cpp_lib_as_rvalue + +#ifdef __cpp_lib_ranges_enumerate // C++ >= 23 + namespace __detail + { + template + concept __range_with_movable_reference = input_range<_Range> + && move_constructible> + && move_constructible>; + } + + template + requires __detail::__range_with_movable_reference<_Vp> + class enumerate_view : public view_interface> + { + _Vp _M_base = _Vp(); + + template class _Iterator; + template class _Sentinel; + + public: + enumerate_view() requires default_initializable<_Vp> = default; + + constexpr explicit + enumerate_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base), 0); } + + constexpr auto + begin() const requires __detail::__range_with_movable_reference + { return _Iterator(ranges::begin(_M_base), 0); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp> && sized_range<_Vp>) + return _Iterator(ranges::end(_M_base), ranges::distance(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires __detail::__range_with_movable_reference + { + if constexpr (common_range && sized_range) + return _Iterator(ranges::end(_M_base), ranges::distance(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + }; + + template + enumerate_view(_Range&&) -> enumerate_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + template + requires __detail::__range_with_movable_reference<_Vp> + template + class enumerate_view<_Vp>::_Iterator + { + using _Base = __maybe_const_t<_Const, _Vp>; + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Base>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend enumerate_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using difference_type = range_difference_t<_Base>; + using value_type = tuple>; + + private: + using __reference_type = tuple>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + difference_type _M_pos = 0; + + constexpr explicit + _Iterator(iterator_t<_Base> __current, difference_type __pos) + : _M_current(std::move(__current)), _M_pos(__pos) + { } + + public: + _Iterator() requires default_initializable> = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_pos(__i._M_pos) + { } + + constexpr const iterator_t<_Base> & + base() const & noexcept + { return _M_current; } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr difference_type + index() const noexcept + { return _M_pos; } + + constexpr auto + operator*() const + { return __reference_type(_M_pos, *_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + ++_M_pos; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + --_M_pos; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + _M_current += __n; + _M_pos += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { + _M_current -= __n; + _M_pos -= __n; + return *this; + } + + constexpr auto + operator[](difference_type __n) const requires random_access_range<_Base> + { return __reference_type(_M_pos + __n, _M_current[__n]); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) noexcept + { return __x._M_pos == __y._M_pos; } + + friend constexpr strong_ordering + operator<=>(const _Iterator& __x, const _Iterator& __y) noexcept + { return __x._M_pos <=> __y._M_pos; } + + friend constexpr _Iterator + operator+(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return (auto(__x) += __y); } + + friend constexpr _Iterator + operator+(difference_type __x, const _Iterator& __y) + requires random_access_range<_Base> + { return auto(__y) += __x; } + + friend constexpr _Iterator + operator-(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return auto(__x) -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + { return __x._M_pos - __y._M_pos; } + + friend constexpr auto + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current)) + && is_nothrow_move_constructible_v>) + { + return tuple> + (__i._M_pos, ranges::iter_move(__i._M_current)); + } + }; + + template + requires __detail::__range_with_movable_reference<_Vp> + template + class enumerate_view<_Vp>::_Sentinel + { + using _Base = __maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(std::move(__end)) + { } + + friend enumerate_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __other) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__other._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current == __y._M_end; } + + template + requires sized_sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current - __y._M_end; } + + template + requires sized_sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_end - __y._M_current; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_enumerate_view + = requires { enumerate_view>(std::declval<_Tp>()); }; + } + + struct _Enumerate : __adaptor::_RangeAdaptorClosure<_Enumerate> + { + template + requires __detail::__can_enumerate_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { return enumerate_view>(std::forward<_Range>(__r)); } + }; + + inline constexpr _Enumerate enumerate; + } +#endif // __cpp_lib_ranges_enumerate + +#ifdef __cpp_lib_ranges_as_const // C++ >= 23 + template + requires input_range<_Vp> + class as_const_view : public view_interface> + { + _Vp _M_base = _Vp(); + + public: + as_const_view() requires default_initializable<_Vp> = default; + + constexpr explicit + as_const_view(_Vp __base) + noexcept(is_nothrow_move_constructible_v<_Vp>) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const & + noexcept(is_nothrow_copy_constructible_v<_Vp>) + requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + noexcept(is_nothrow_move_constructible_v<_Vp>) + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::cbegin(_M_base); } + + constexpr auto + begin() const requires range + { return ranges::cbegin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::cend(_M_base); } + + constexpr auto + end() const requires range + { return ranges::cend(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + as_const_view(_Range&&) -> as_const_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_ref_view = false; + + template + inline constexpr bool __is_ref_view> = true; + + template + concept __can_as_const_view = requires { as_const_view(std::declval<_Range>()); }; + } + + struct _AsConst : __adaptor::_RangeAdaptorClosure<_AsConst> + { + template + constexpr auto + operator()(_Range&& __r) const + noexcept(noexcept(as_const_view(std::declval<_Range>()))) + requires __detail::__can_as_const_view<_Range> + { + using _Tp = remove_cvref_t<_Range>; + using element_type = remove_reference_t>; + if constexpr (constant_range>) + return views::all(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_empty_view<_Tp>) + return views::empty; + else if constexpr (std::__detail::__is_span<_Tp>) + return span(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_ref_view<_Tp> + && constant_range) + return ref_view(static_cast + (std::forward<_Range>(__r).base())); + else if constexpr (is_lvalue_reference_v<_Range> + && constant_range + && !view<_Tp>) + return ref_view(static_cast(__r)); + else + return as_const_view(std::forward<_Range>(__r)); + } + }; + + inline constexpr _AsConst as_const; + } +#endif // __cpp_lib_as_const +} // namespace ranges + + namespace views = ranges::views; + +#if __cpp_lib_ranges_to_container // C++ >= 23 +namespace ranges +{ +/// @cond undocumented +namespace __detail +{ + template + constexpr bool __reservable_container + = sized_range<_Container> + && requires(_Container& __c, range_size_t<_Container> __n) { + __c.reserve(__n); + { __c.capacity() } -> same_as; + { __c.max_size() } -> same_as; + }; + + template + constexpr bool __toable = requires { + requires (!input_range<_Cont> + || convertible_to, + range_value_t<_Cont>>); + }; +} // namespace __detail +/// @endcond + + /// Convert a range to a container. + /** + * @tparam _Cont A container type. + * @param __r A range that models the `input_range` concept. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This function converts a range to the `_Cont` type. + * + * For example, `std::ranges::to>(some_view)` + * will convert the view to `std::vector`. + * + * Additional constructor arguments for the container can be supplied after + * the input range argument, e.g. + * `std::ranges::to>>(a_range, an_allocator)`. + */ + template + requires (!view<_Cont>) + constexpr _Cont + to [[nodiscard]] (_Rg&& __r, _Args&&... __args) + { + static_assert(!is_const_v<_Cont> && !is_volatile_v<_Cont>); + static_assert(is_class_v<_Cont>); + + if constexpr (__detail::__toable<_Cont, _Rg>) + { + if constexpr (constructible_from<_Cont, _Rg, _Args...>) + return _Cont(std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (constructible_from<_Cont, from_range_t, _Rg, _Args...>) + return _Cont(from_range, std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (requires { requires common_range<_Rg>; + typename __iter_category_t>; + requires derived_from<__iter_category_t>, + input_iterator_tag>; + requires constructible_from<_Cont, iterator_t<_Rg>, + sentinel_t<_Rg>, _Args...>; + }) + return _Cont(ranges::begin(__r), ranges::end(__r), + std::forward<_Args>(__args)...); + else + { + using _RefT = range_reference_t<_Rg>; + static_assert(constructible_from<_Cont, _Args...>); + _Cont __c(std::forward<_Args>(__args)...); + if constexpr (sized_range<_Rg> + && __detail::__reservable_container<_Cont>) + __c.reserve(static_cast>(ranges::size(__r))); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4016. container-insertable checks do not match what + // container-inserter does + auto __it = ranges::begin(__r); + const auto __sent = ranges::end(__r); + while (__it != __sent) + { + if constexpr (requires { __c.emplace_back(*__it); }) + __c.emplace_back(*__it); + else if constexpr (requires { __c.push_back(*__it); }) + __c.push_back(*__it); + else if constexpr (requires { __c.emplace(__c.end(), *__it); }) + __c.emplace(__c.end(), *__it); + else + __c.insert(__c.end(), *__it); + ++__it; + } + return __c; + } + } + else + { + static_assert(input_range>); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3984. ranges::to's recursion branch may be ill-formed + return ranges::to<_Cont>(ref_view(__r) | views::transform( + [](_Elt&& __elem) { + using _ValT = range_value_t<_Cont>; + return ranges::to<_ValT>(std::forward<_Elt>(__elem)); + }), std::forward<_Args>(__args)...); + } + } + +/// @cond undocumented +namespace __detail +{ + template + struct _InputIter + { + using iterator_category = input_iterator_tag; + using value_type = range_value_t<_Rg>; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t<_Rg>; + reference operator*() const; + pointer operator->() const; + _InputIter& operator++(); + _InputIter operator++(int); + bool operator==(const _InputIter&) const; + }; + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr1 + = decltype(_Cont(std::declval<_Rg>(), std::declval<_Args>()...)); + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr2 + = decltype(_Cont(from_range, std::declval<_Rg>(), + std::declval<_Args>()...)); + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr3 + = decltype(_Cont(std::declval<_InputIter<_Rg>>(), + std::declval<_InputIter<_Rg>>(), + std::declval<_Args>()...)); + +} // namespace __detail +/// @endcond + + template typename _Cont, input_range _Rg, + typename... _Args> + constexpr auto + to [[nodiscard]] (_Rg&& __r, _Args&&... __args) + { + using __detail::_DeduceExpr1; + using __detail::_DeduceExpr2; + using __detail::_DeduceExpr3; + if constexpr (requires { typename _DeduceExpr1<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr1<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr2<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr2<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr3<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr3<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else + static_assert(false); // Cannot deduce container specialization. + } + +/// @cond undocumented +namespace __detail +{ + template + struct _To + { + template + requires requires { ranges::to<_Cont>(std::declval<_Range>(), + std::declval<_Args>()...); } + constexpr auto + operator()(_Range&& __r, _Args&&... __args) const + { + return ranges::to<_Cont>(std::forward<_Range>(__r), + std::forward<_Args>(__args)...); + } + }; +} // namespace __detail +/// @endcond + + /// ranges::to adaptor for converting a range to a container type + /** + * @tparam _Cont A container type. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This range adaptor returns a range adaptor closure object that converts + * a range to the `_Cont` type. + * + * For example, `some_view | std::ranges::to>()` + * will convert the view to `std::vector`. + * + * Additional constructor arguments for the container can be supplied, e.g. + * `r | std::ranges::to>>(an_allocator)`. + */ + template + requires (!view<_Cont>) + constexpr auto + to [[nodiscard]] (_Args&&... __args) + { + using __detail::_To; + using views::__adaptor::_Partial; + return _Partial<_To<_Cont>, decay_t<_Args>...>{0, std::forward<_Args>(__args)...}; + } + +/// @cond undocumented +namespace __detail +{ + template typename _Cont> + struct _To2 + { + template + requires requires { ranges::to<_Cont>(std::declval<_Range>(), + std::declval<_Args>()...); } + constexpr auto + operator()(_Range&& __r, _Args&&... __args) const + { + return ranges::to<_Cont>(std::forward<_Range>(__r), + std::forward<_Args>(__args)...); + } + }; +} // namespace __detail +/// @endcond + + /// ranges::to adaptor for converting a range to a deduced container type. + /** + * @tparam _Cont A container template. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This range adaptor returns a range adaptor closure object that converts + * a range to a specialization of the `_Cont` class template. The specific + * specialization of `_Cont` to be used is deduced automatically. + * + * For example, `some_view | std::ranges::to(Alloc{})` + * will convert the view to `std::vector>`, where `T` is the + * view's value type, i.e. `std::ranges::range_value_t`. + * + * Additional constructor arguments for the container can be supplied, e.g. + * `r | std::ranges::to(an_allocator)`. + */ + template typename _Cont, typename... _Args> + constexpr auto + to [[nodiscard]] (_Args&&... __args) + { + using __detail::_To2; + using views::__adaptor::_Partial; + return _Partial<_To2<_Cont>, decay_t<_Args>...>{0, std::forward<_Args>(__args)...}; + } + +} // namespace ranges +#endif // __cpp_lib_ranges_to_container + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // library concepts +#endif // C++2a +#endif /* _GLIBCXX_RANGES */ diff --git a/template/sysroot/include/raointintrin.h b/template/sysroot/include/raointintrin.h new file mode 100644 index 0000000..2143621 --- /dev/null +++ b/template/sysroot/include/raointintrin.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2019-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif // _X86GPRINTRIN_H_INCLUDED + +#ifndef __RAOINTINTRIN_H_INCLUDED +#define __RAOINTINTRIN_H_INCLUDED + +#ifndef __RAOINT__ +#pragma GCC push_options +#pragma GCC target("raoint") +#define __DISABLE_RAOINT__ +#endif /* __RAOINT__ */ + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aadd_i32 (int *__A, int __B) +{ + __builtin_ia32_aadd32 ((int *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aand_i32 (int *__A, int __B) +{ + __builtin_ia32_aand32 ((int *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aor_i32 (int *__A, int __B) +{ + __builtin_ia32_aor32 ((int *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_axor_i32 (int *__A, int __B) +{ + __builtin_ia32_axor32 ((int *)__A, __B); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aadd_i64 (long long *__A, long long __B) +{ + __builtin_ia32_aadd64 ((long long *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aand_i64 (long long *__A, long long __B) +{ + __builtin_ia32_aand64 ((long long *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_aor_i64 (long long *__A, long long __B) +{ + __builtin_ia32_aor64 ((long long *)__A, __B); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_axor_i64 (long long *__A, long long __B) +{ + __builtin_ia32_axor64 ((long long *)__A, __B); +} +#endif /* __x86_64__ */ + +#ifdef __DISABLE_RAOINT__ +#undef __DISABLE_RAOINT__ +#pragma GCC pop_options +#endif /* __DISABLE_RAOINT__ */ + +#endif /* __RAOINTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/ratio b/template/sysroot/include/ratio new file mode 100644 index 0000000..d80a981 --- /dev/null +++ b/template/sysroot/include/ratio @@ -0,0 +1,651 @@ +// ratio -*- C++ -*- + +// Copyright (C) 2008-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ratio + * This is a Standard C++ Library header. + * @ingroup ratio + */ + +#ifndef _GLIBCXX_RATIO +#define _GLIBCXX_RATIO 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include // intmax_t, uintmax_t + +#define __glibcxx_want_ratio +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup ratio Rational Arithmetic + * @ingroup utilities + * + * Compile time representation of finite rational numbers. + * @{ + */ + + /// @cond undocumented + + template + struct __static_sign + : integral_constant + { }; + + template + struct __static_abs + : integral_constant::value> + { }; + + template + struct __static_gcd + : __static_gcd<_Qn, (_Pn % _Qn)> + { }; + + template + struct __static_gcd<_Pn, 0> + : integral_constant::value> + { }; + + template + struct __static_gcd<0, _Qn> + : integral_constant::value> + { }; + + // Let c = 2^(half # of bits in an intmax_t) + // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 + // The multiplication of N and M becomes, + // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 + // Multiplication is safe if each term and the sum of the terms + // is representable by intmax_t. + template + struct __safe_multiply + { + private: + static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + + static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; + static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; + static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; + static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; + + static_assert(__a1 == 0 || __b1 == 0, + "overflow in multiplication"); + static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), + "overflow in multiplication"); + static_assert(__b0 * __a0 <= __INTMAX_MAX__, + "overflow in multiplication"); + static_assert((__a0 * __b1 + __b0 * __a1) * __c + <= __INTMAX_MAX__ - __b0 * __a0, + "overflow in multiplication"); + + public: + static const intmax_t value = _Pn * _Qn; + }; + + // Some double-precision utilities, where numbers are represented as + // __hi*2^(8*sizeof(uintmax_t)) + __lo. + template + struct __big_less + : integral_constant + { }; + + template + struct __big_add + { + static constexpr uintmax_t __lo = __lo1 + __lo2; + static constexpr uintmax_t __hi = (__hi1 + __hi2 + + (__lo1 + __lo2 < __lo1)); // carry + }; + + // Subtract a number from a bigger one. + template + struct __big_sub + { + static_assert(!__big_less<__hi1, __lo1, __hi2, __lo2>::value, + "Internal library error"); + static constexpr uintmax_t __lo = __lo1 - __lo2; + static constexpr uintmax_t __hi = (__hi1 - __hi2 - + (__lo1 < __lo2)); // carry + }; + + // Same principle as __safe_multiply. + template + struct __big_mul + { + private: + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __x0 = __x % __c; + static constexpr uintmax_t __x1 = __x / __c; + static constexpr uintmax_t __y0 = __y % __c; + static constexpr uintmax_t __y1 = __y / __c; + static constexpr uintmax_t __x0y0 = __x0 * __y0; + static constexpr uintmax_t __x0y1 = __x0 * __y1; + static constexpr uintmax_t __x1y0 = __x1 * __y0; + static constexpr uintmax_t __x1y1 = __x1 * __y1; + static constexpr uintmax_t __mix = __x0y1 + __x1y0; // possible carry... + static constexpr uintmax_t __mix_lo = __mix * __c; + static constexpr uintmax_t __mix_hi + = __mix / __c + ((__mix < __x0y1) ? __c : 0); // ... added here + typedef __big_add<__mix_hi, __mix_lo, __x1y1, __x0y0> _Res; + public: + static constexpr uintmax_t __hi = _Res::__hi; + static constexpr uintmax_t __lo = _Res::__lo; + }; + + // Adapted from __udiv_qrnnd_c in longlong.h + // This version assumes that the high bit of __d is 1. + template + struct __big_div_impl + { + private: + static_assert(__d >= (uintmax_t(1) << (sizeof(intmax_t) * 8 - 1)), + "Internal library error"); + static_assert(__n1 < __d, "Internal library error"); + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __d1 = __d / __c; + static constexpr uintmax_t __d0 = __d % __c; + + static constexpr uintmax_t __q1x = __n1 / __d1; + static constexpr uintmax_t __r1x = __n1 % __d1; + static constexpr uintmax_t __m = __q1x * __d0; + static constexpr uintmax_t __r1y = __r1x * __c + __n0 / __c; + static constexpr uintmax_t __r1z = __r1y + __d; + static constexpr uintmax_t __r1 + = ((__r1y < __m) ? ((__r1z >= __d) && (__r1z < __m)) + ? (__r1z + __d) : __r1z : __r1y) - __m; + static constexpr uintmax_t __q1 + = __q1x - ((__r1y < __m) + ? ((__r1z >= __d) && (__r1z < __m)) ? 2 : 1 : 0); + static constexpr uintmax_t __q0x = __r1 / __d1; + static constexpr uintmax_t __r0x = __r1 % __d1; + static constexpr uintmax_t __n = __q0x * __d0; + static constexpr uintmax_t __r0y = __r0x * __c + __n0 % __c; + static constexpr uintmax_t __r0z = __r0y + __d; + static constexpr uintmax_t __r0 + = ((__r0y < __n) ? ((__r0z >= __d) && (__r0z < __n)) + ? (__r0z + __d) : __r0z : __r0y) - __n; + static constexpr uintmax_t __q0 + = __q0x - ((__r0y < __n) ? ((__r0z >= __d) + && (__r0z < __n)) ? 2 : 1 : 0); + + public: + static constexpr uintmax_t __quot = __q1 * __c + __q0; + static constexpr uintmax_t __rem = __r0; + + private: + typedef __big_mul<__quot, __d> _Prod; + typedef __big_add<_Prod::__hi, _Prod::__lo, 0, __rem> _Sum; + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + }; + + template + struct __big_div + { + private: + static_assert(__d != 0, "Internal library error"); + static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), + "This library calls __builtin_clzll on uintmax_t, which " + "is unsafe on your platform. Please complain to " + "http://gcc.gnu.org/bugzilla/"); + static constexpr int __shift = __builtin_clzll(__d); + static constexpr int __coshift_ = sizeof(uintmax_t) * 8 - __shift; + static constexpr int __coshift = (__shift != 0) ? __coshift_ : 0; + static constexpr uintmax_t __c1 = uintmax_t(1) << __shift; + static constexpr uintmax_t __c2 = uintmax_t(1) << __coshift; + static constexpr uintmax_t __new_d = __d * __c1; + static constexpr uintmax_t __new_n0 = __n0 * __c1; + static constexpr uintmax_t __n1_shifted = (__n1 % __d) * __c1; + static constexpr uintmax_t __n0_top = (__shift != 0) ? (__n0 / __c2) : 0; + static constexpr uintmax_t __new_n1 = __n1_shifted + __n0_top; + typedef __big_div_impl<__new_n1, __new_n0, __new_d> _Res; + + public: + static constexpr uintmax_t __quot_hi = __n1 / __d; + static constexpr uintmax_t __quot_lo = _Res::__quot; + static constexpr uintmax_t __rem = _Res::__rem / __c1; + + private: + typedef __big_mul<__quot_lo, __d> _P0; + typedef __big_mul<__quot_hi, __d> _P1; + typedef __big_add<_P0::__hi, _P0::__lo, _P1::__lo, __rem> _Sum; + // No overflow. + static_assert(_P1::__hi == 0, "Internal library error"); + static_assert(_Sum::__hi >= _P0::__hi, "Internal library error"); + // Matches the input data. + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + static_assert(__rem < __d, "Internal library error"); + }; + + /// @endcond + + /** + * @brief Provides compile-time rational arithmetic. + * + * This class template represents any finite rational number with a + * numerator and denominator representable by compile-time constants of + * type intmax_t. The ratio is simplified when instantiated. + * + * For example: + * @code + * std::ratio<7,-21>::num == -1; + * std::ratio<7,-21>::den == 3; + * @endcode + * + */ + template + struct ratio + { + static_assert(_Den != 0, "denominator cannot be zero"); + static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, + "out of range"); + + // Note: sign(N) * abs(N) == N + static constexpr intmax_t num = + _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; + + static constexpr intmax_t den = + __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; + + typedef ratio type; + }; + +#if ! __cpp_inline_variables + template + constexpr intmax_t ratio<_Num, _Den>::num; + + template + constexpr intmax_t ratio<_Num, _Den>::den; +#endif + + /// @cond undocumented + + template + struct __is_ratio + : std::false_type + { }; + + template + struct __is_ratio> + : std::true_type + { }; + +#if __cpp_variable_templates + template + constexpr bool __is_ratio_v = false; + template + constexpr bool __is_ratio_v> = true; +#endif + + template + constexpr bool + __are_both_ratios() noexcept + { +#if __cpp_variable_templates && __cpp_if_constexpr + if constexpr (__is_ratio_v<_R1>) + if constexpr (__is_ratio_v<_R2>) + return true; + return false; +#else + return __and_<__is_ratio<_R1>, __is_ratio<_R2>>::value; +#endif + } + + template + struct __ratio_multiply + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + + private: + static const intmax_t __gcd1 = + __static_gcd<_R1::num, _R2::den>::value; + static const intmax_t __gcd2 = + __static_gcd<_R2::num, _R1::den>::value; + + public: + typedef ratio< + __safe_multiply<(_R1::num / __gcd1), + (_R2::num / __gcd2)>::value, + __safe_multiply<(_R1::den / __gcd2), + (_R2::den / __gcd1)>::value> type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + +#if ! __cpp_inline_variables + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::den; +#endif + + /// @endcond + + /// ratio_multiply + template + using ratio_multiply = typename __ratio_multiply<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_divide + { + static_assert(_R2::num != 0, "division by 0"); + + typedef typename __ratio_multiply< + _R1, + ratio<_R2::den, _R2::num>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + +#if ! __cpp_inline_variables + template + constexpr intmax_t __ratio_divide<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_divide<_R1, _R2>::den; +#endif + + /// @endcond + + /// ratio_divide + template + using ratio_divide = typename __ratio_divide<_R1, _R2>::type; + + /// ratio_equal + template + struct ratio_equal + : integral_constant + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; + + /// ratio_not_equal + template + struct ratio_not_equal + : integral_constant::value> + { }; + + /// @cond undocumented + + // Both numbers are positive. + template, + typename _Right = __big_mul<_R2::num,_R1::den> > + struct __ratio_less_impl_1 + : integral_constant::value> + { }; + + template::value + != __static_sign<_R2::num>::value)), + bool = (__static_sign<_R1::num>::value == -1 + && __static_sign<_R2::num>::value == -1)> + struct __ratio_less_impl + : __ratio_less_impl_1<_R1, _R2>::type + { }; + + template + struct __ratio_less_impl<_R1, _R2, true, false> + : integral_constant + { }; + + template + struct __ratio_less_impl<_R1, _R2, false, true> + : __ratio_less_impl_1, + ratio<-_R1::num, _R1::den> >::type + { }; + + /// @endcond + + /// ratio_less + template + struct ratio_less + : __ratio_less_impl<_R1, _R2>::type + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; + + /// ratio_less_equal + template + struct ratio_less_equal + : integral_constant::value> + { }; + + /// ratio_greater + template + struct ratio_greater + : integral_constant::value> + { }; + + /// ratio_greater_equal + template + struct ratio_greater_equal + : integral_constant::value> + { }; + +#if __cplusplus > 201402L + template + inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_not_equal_v = ratio_not_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; + template + inline constexpr bool ratio_less_equal_v + = ratio_less_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_equal_v + = ratio_greater_equal<_R1, _R2>::value; +#endif // C++17 + + /// @cond undocumented + + template= 0), + bool = (_R2::num >= 0), + bool = ratio_less::value, _R1::den>, + ratio<__static_abs<_R2::num>::value, _R2::den> >::value> + struct __ratio_add_impl + { + private: + typedef typename __ratio_add_impl< + ratio<-_R1::num, _R1::den>, + ratio<-_R2::num, _R2::den> >::type __t; + public: + typedef ratio<-__t::num, __t::den> type; + }; + + // True addition of nonnegative numbers. + template + struct __ratio_add_impl<_R1, _R2, true, true, __b> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<_R2::num, _R1::den / __g> __y; + typedef __big_add<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + static_assert(__n::__hi >= __x::__hi, "Internal library error"); + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add_impl<_R1, _R2, false, true, true> + : __ratio_add_impl<_R2, _R1> + { }; + + // True subtraction of nonnegative numbers yielding a nonnegative result. + template + struct __ratio_add_impl<_R1, _R2, true, false, false> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<-_R2::num, _R1::den / __g> __y; + typedef __big_sub<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + + typedef typename __ratio_add_impl<_R1, _R2>::type type; + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + +#if ! __cpp_inline_variables + template + constexpr intmax_t __ratio_add<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_add<_R1, _R2>::den; +#endif + + /// @endcond + + /// ratio_add + template + using ratio_add = typename __ratio_add<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_subtract + { + typedef typename __ratio_add< + _R1, + ratio<-_R2::num, _R2::den>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + +#if ! __cpp_inline_variables + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::den; +#endif + + /// @endcond + + /// ratio_subtract + template + using ratio_subtract = typename __ratio_subtract<_R1, _R2>::type; + +#if __INTMAX_WIDTH__ >= 96 +# if __cpp_lib_ratio >= 202306L +# if __INTMAX_WIDTH__ >= 128 + using quecto = ratio< 1, 1000000000000000000000000000000>; +# endif + using ronto = ratio< 1, 1000000000000000000000000000>; +# endif + using yocto = ratio< 1, 1000000000000000000000000>; + using zepto = ratio< 1, 1000000000000000000000>; +#endif + using atto = ratio< 1, 1000000000000000000>; + using femto = ratio< 1, 1000000000000000>; + using pico = ratio< 1, 1000000000000>; + using nano = ratio< 1, 1000000000>; + using micro = ratio< 1, 1000000>; + using milli = ratio< 1, 1000>; + using centi = ratio< 1, 100>; + using deci = ratio< 1, 10>; + using deca = ratio< 10, 1>; + using hecto = ratio< 100, 1>; + using kilo = ratio< 1000, 1>; + using mega = ratio< 1000000, 1>; + using giga = ratio< 1000000000, 1>; + using tera = ratio< 1000000000000, 1>; + using peta = ratio< 1000000000000000, 1>; + using exa = ratio< 1000000000000000000, 1>; +#if __INTMAX_WIDTH__ >= 96 + using zetta = ratio< 1000000000000000000000, 1>; + using yotta = ratio<1000000000000000000000000, 1>; +# if __cpp_lib_ratio >= 202306L + using ronna = ratio<1000000000000000000000000000, 1>; +# if __INTMAX_WIDTH__ >= 128 + using quetta = ratio<1000000000000000000000000000000, 1>; +# endif +# endif +#endif + + /// @} group ratio +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif //_GLIBCXX_RATIO diff --git a/template/sysroot/include/rdseedintrin.h b/template/sysroot/include/rdseedintrin.h new file mode 100644 index 0000000..808ba8e --- /dev/null +++ b/template/sysroot/include/rdseedintrin.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _RDSEEDINTRIN_H_INCLUDED +#define _RDSEEDINTRIN_H_INCLUDED + +#ifndef __RDSEED__ +#pragma GCC push_options +#pragma GCC target("rdseed") +#define __DISABLE_RDSEED__ +#endif /* __RDSEED__ */ + + +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdseed16_step (unsigned short *__p) +{ + return __builtin_ia32_rdseed_hi_step (__p); +} + +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdseed32_step (unsigned int *__p) +{ + return __builtin_ia32_rdseed_si_step (__p); +} + +#ifdef __x86_64__ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdseed64_step (unsigned long long *__p) +{ + return __builtin_ia32_rdseed_di_step (__p); +} +#endif + +#ifdef __DISABLE_RDSEED__ +#undef __DISABLE_RDSEED__ +#pragma GCC pop_options +#endif /* __DISABLE_RDSEED__ */ + +#endif /* _RDSEEDINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/rtmintrin.h b/template/sysroot/include/rtmintrin.h new file mode 100644 index 0000000..2c3fc71 --- /dev/null +++ b/template/sysroot/include/rtmintrin.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _RTMINTRIN_H_INCLUDED +#define _RTMINTRIN_H_INCLUDED + +#ifndef __RTM__ +#pragma GCC push_options +#pragma GCC target("rtm") +#define __DISABLE_RTM__ +#endif /* __RTM__ */ + +#define _XBEGIN_STARTED (~0u) +#define _XABORT_EXPLICIT (1 << 0) +#define _XABORT_RETRY (1 << 1) +#define _XABORT_CONFLICT (1 << 2) +#define _XABORT_CAPACITY (1 << 3) +#define _XABORT_DEBUG (1 << 4) +#define _XABORT_NESTED (1 << 5) +#define _XABORT_CODE(x) (((x) >> 24) & 0xFF) + +/* Start an RTM code region. Return _XBEGIN_STARTED on success and the + abort condition otherwise. */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xbegin (void) +{ + return __builtin_ia32_xbegin (); +} + +/* Specify the end of an RTM code region. If it corresponds to the + outermost transaction, then attempts the transaction commit. If the + commit fails, then control is transferred to the outermost transaction + fallback handler. */ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xend (void) +{ + __builtin_ia32_xend (); +} + +/* Force an RTM abort condition. The control is transferred to the + outermost transaction fallback handler with the abort condition IMM. */ +#ifdef __OPTIMIZE__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xabort (const unsigned int __imm) +{ + __builtin_ia32_xabort (__imm); +} +#else +#define _xabort(N) __builtin_ia32_xabort (N) +#endif /* __OPTIMIZE__ */ + +#ifdef __DISABLE_RTM__ +#undef __DISABLE_RTM__ +#pragma GCC pop_options +#endif /* __DISABLE_RTM__ */ + +#endif /* _RTMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/scoped_allocator b/template/sysroot/include/scoped_allocator new file mode 100644 index 0000000..dbe7bf3 --- /dev/null +++ b/template/sysroot/include/scoped_allocator @@ -0,0 +1,528 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/scoped_allocator + * This is a Standard C++ Library header. + */ + +#ifndef _SCOPED_ALLOCATOR +#define _SCOPED_ALLOCATOR 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + template + class scoped_allocator_adaptor; + + /// @cond undocumented + + template + using __outer_allocator_t + = decltype(std::declval<_Alloc>().outer_allocator()); + + template + struct __outermost_type + { + using type = _Alloc; + static type& _S_outermost(_Alloc& __a) noexcept { return __a; } + }; + + template + struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> + : __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + > + { + using __base = __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + >; + + static typename __base::type& + _S_outermost(_Alloc& __a) noexcept + { return __base::_S_outermost(__a.outer_allocator()); } + }; + + // Implementation of the OUTERMOST pseudofunction + template + inline typename __outermost_type<_Alloc>::type& + __outermost(_Alloc& __a) + { return __outermost_type<_Alloc>::_S_outermost(__a); } + + template + struct __inner_type_impl; + + template + struct __inner_type_impl<_Outer> + { + typedef scoped_allocator_adaptor<_Outer> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Alloc>&) noexcept + { } + + template + __inner_type_impl(__inner_type_impl<_Alloc>&&) noexcept + { } + + __type& + _M_get(__type* __p) noexcept { return *__p; } + + const __type& + _M_get(const __type* __p) const noexcept { return *__p; } + + tuple<> + _M_tie() const noexcept { return tuple<>(); } + + bool + operator==(const __inner_type_impl&) const noexcept + { return true; } + }; + + template + struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> + { + typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) noexcept + : _M_inner(__other._M_inner) { } + + template + __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) noexcept + : _M_inner(std::move(__other._M_inner)) { } + + template + explicit + __inner_type_impl(_Args&&... __args) noexcept + : _M_inner(std::forward<_Args>(__args)...) { } + + __type& + _M_get(void*) noexcept { return _M_inner; } + + const __type& + _M_get(const void*) const noexcept { return _M_inner; } + + tuple + _M_tie() const noexcept + { return _M_inner._M_tie(); } + + bool + operator==(const __inner_type_impl& __other) const noexcept + { return _M_inner == __other._M_inner; } + + private: + template friend struct __inner_type_impl; + template friend class scoped_allocator_adaptor; + + __type _M_inner; + }; + + /// @endcond + + /// An adaptor to recursively pass an allocator to the objects it constructs + template + class scoped_allocator_adaptor + : public _OuterAlloc + { + typedef allocator_traits<_OuterAlloc> __traits; + + typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; + __inner_type _M_inner; + + template + friend class scoped_allocator_adaptor; + + template + friend struct __inner_type_impl; + + tuple + _M_tie() const noexcept + { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } + + template + using __outermost_alloc_traits + = allocator_traits::type>; + +#if ! __glibcxx_make_obj_using_allocator + template + void + _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)...); + } + + typedef __uses_alloc1 __uses_alloc1_; + typedef __uses_alloc2 __uses_alloc2_; + + template + void + _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + allocator_arg, inner_allocator(), + std::forward<_Args>(__args)...); + } + + template + void + _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)..., + inner_allocator()); + } +#endif // ! make_obj_using_allocator + + template + static _Alloc + _S_select_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __a_traits; + return __a_traits::select_on_container_copy_construction(__a); + } + + template + scoped_allocator_adaptor(tuple __refs, + _Index_tuple<_Indices...>) + : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), + _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) + { } + + // Used to constrain constructors to disallow invalid conversions. + template + using _Constructible = typename enable_if< + is_constructible<_OuterAlloc, _Alloc>::value + >::type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2975. Missing case for pair construction in scoped [...] allocators + template + struct __not_pair { using type = void; }; + + template + struct __not_pair> { }; + + public: + typedef _OuterAlloc outer_allocator_type; + typedef typename __inner_type::__type inner_allocator_type; + + typedef typename __traits::value_type value_type; + typedef typename __traits::size_type size_type; + typedef typename __traits::difference_type difference_type; + typedef typename __traits::pointer pointer; + typedef typename __traits::const_pointer const_pointer; + typedef typename __traits::void_pointer void_pointer; + typedef typename __traits::const_void_pointer const_void_pointer; + + typedef typename __or_< + typename __traits::propagate_on_container_copy_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_copy_assignment...>::type + propagate_on_container_copy_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_move_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_move_assignment...>::type + propagate_on_container_move_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_swap, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_swap...>::type + propagate_on_container_swap; + + typedef typename __and_< + typename __traits::is_always_equal, + typename allocator_traits<_InnerAllocs>::is_always_equal...>::type + is_always_equal; + + template + struct rebind + { + typedef scoped_allocator_adaptor< + typename __traits::template rebind_alloc<_Tp>, + _InnerAllocs...> other; + }; + + scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } + + template> + scoped_allocator_adaptor(_Outer2&& __outer, + const _InnerAllocs&... __inner) noexcept + : _OuterAlloc(std::forward<_Outer2>(__outer)), + _M_inner(__inner...) + { } + + scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) noexcept + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) noexcept + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + template> + scoped_allocator_adaptor( + const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other + ) noexcept + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + template> + scoped_allocator_adaptor( + scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) noexcept + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + scoped_allocator_adaptor& + operator=(const scoped_allocator_adaptor&) = default; + + scoped_allocator_adaptor& + operator=(scoped_allocator_adaptor&&) = default; + + inner_allocator_type& + inner_allocator() noexcept + { return _M_inner._M_get(this); } + + const inner_allocator_type& + inner_allocator() const noexcept + { return _M_inner._M_get(this); } + + outer_allocator_type& + outer_allocator() noexcept + { return static_cast<_OuterAlloc&>(*this); } + + const outer_allocator_type& + outer_allocator() const noexcept + { return static_cast(*this); } + + _GLIBCXX_NODISCARD pointer + allocate(size_type __n) + { return __traits::allocate(outer_allocator(), __n); } + + _GLIBCXX_NODISCARD pointer + allocate(size_type __n, const_void_pointer __hint) + { return __traits::allocate(outer_allocator(), __n, __hint); } + + void deallocate(pointer __p, size_type __n) noexcept + { return __traits::deallocate(outer_allocator(), __p, __n); } + + size_type max_size() const + { return __traits::max_size(outer_allocator()); } + +#if ! __glibcxx_make_obj_using_allocator + template + typename __not_pair<_Tp>::type + construct(_Tp* __p, _Args&&... __args) + { + auto& __inner = inner_allocator(); + auto __use_tag + = std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); + _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); + } + + template + void + construct(pair<_T1, _T2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2203. wrong argument types for piecewise construction + auto& __inner = inner_allocator(); + auto __x_use_tag + = std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); + auto __y_use_tag + = std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); + typename _Build_index_tuple::__type __x_indices; + typename _Build_index_tuple::__type __y_indices; + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, piecewise_construct, + _M_construct_p(__x_use_tag, __x_indices, __x), + _M_construct_p(__y_use_tag, __y_indices, __y)); + } + + template + void + construct(pair<_T1, _T2>* __p) + { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } + + template + void + construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__u)), + std::forward_as_tuple(std::forward<_Vp>(__v))); + } + + template + void + construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(__x.first), + std::forward_as_tuple(__x.second)); + } + + template + void + construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__x.first)), + std::forward_as_tuple(std::forward<_Vp>(__x.second))); + } +#else // make_obj_using_allocator + template + __attribute__((__nonnull__)) + void + construct(_Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + std::apply([__p, this](auto&&... __newargs) { + _O_traits::construct(__outermost(*this), __p, + std::forward(__newargs)...); + }, + uses_allocator_construction_args<_Tp>(inner_allocator(), + std::forward<_Args>(__args)...)); + } +#endif + + template + void destroy(_Tp* __p) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::destroy(__outermost(*this), __p); + } + + scoped_allocator_adaptor + select_on_container_copy_construction() const + { + typedef typename _Build_index_tuple::__type + _Indices; + return scoped_allocator_adaptor(_M_tie(), _Indices()); + } + + template + friend bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; + + private: +#if ! __glibcxx_make_obj_using_allocator + template + tuple<_Args&&...> + _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) + { return std::move(__t); } + + template + tuple + _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { allocator_arg, inner_allocator(), + std::get<_Ind>(std::move(__t))... + }; + } + + template + tuple<_Args&&..., inner_allocator_type&> + _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; + } +#endif // ! make_obj_using_allocator + }; + + /// @related std::scoped_allocator_adaptor + template + inline bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { + return __a.outer_allocator() == __b.outer_allocator() + && __a._M_inner == __b._M_inner; + } + +#if __cpp_impl_three_way_comparison < 201907L + /// @related std::scoped_allocator_adaptor + template + inline bool + operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { return !(__a == __b); } +#endif + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _SCOPED_ALLOCATOR diff --git a/template/sysroot/include/serializeintrin.h b/template/sysroot/include/serializeintrin.h new file mode 100644 index 0000000..951757a --- /dev/null +++ b/template/sysroot/include/serializeintrin.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _SERIALIZE_H_INCLUDED +#define _SERIALIZE_H_INCLUDED + +#ifndef __SERIALIZE__ +#pragma GCC push_options +#pragma GCC target("serialize") +#define __DISABLE_SERIALIZE__ +#endif /* __SERIALIZE__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_serialize (void) +{ + __builtin_ia32_serialize (); +} + +#ifdef __DISABLE_SERIALIZE__ +#undef __DISABLE_SERIALIZE__ +#pragma GCC pop_options +#endif /* __DISABLE_SERIALIZE__ */ + +#endif /* _SERIALIZE_H_INCLUDED. */ diff --git a/template/sysroot/include/sgxintrin.h b/template/sysroot/include/sgxintrin.h new file mode 100644 index 0000000..23cd592 --- /dev/null +++ b/template/sysroot/include/sgxintrin.h @@ -0,0 +1,253 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _SGXINTRIN_H_INCLUDED +#define _SGXINTRIN_H_INCLUDED + +#ifndef __SGX__ +#pragma GCC push_options +#pragma GCC target("sgx") +#define __DISABLE_SGX__ +#endif /* __SGX__ */ + +#define __encls_bc(leaf, b, c, retval) \ + __asm__ __volatile__ ("encls\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b), "c" (c) \ + : "cc") + +#define __encls_bcd(leaf, b, c, d, retval) \ + __asm__ __volatile__("encls\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +#define __encls_c(leaf, c, retval) \ + __asm__ __volatile__("encls\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "c" (c) \ + : "cc") + +#define __encls_edbgrd(leaf, b, c, retval) \ + __asm__ __volatile__("encls\n\t" \ + : "=a" (retval), "=b" (b) \ + : "a" (leaf), "c" (c)) + +#define __encls_generic(leaf, b, c, d, retval) \ + __asm__ __volatile__("encls\n\t" \ + : "=a" (retval), "=b" (b), "=c" (c), "=d" (d)\ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +#define __enclu_bc(leaf, b, c, retval) \ + __asm__ __volatile__("enclu\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b), "c" (c) \ + : "cc") + +#define __enclu_bcd(leaf, b, c, d, retval) \ + __asm__ __volatile__("enclu\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +#define __enclu_eenter(leaf, b, c, retval) \ + __asm__ __volatile__("enclu\n\t" \ + : "=a" (retval), "=c" (c) \ + : "a" (leaf), "b" (b), "c" (c) \ + : "cc") + +#define __enclu_eexit(leaf, b, c, retval) \ + __asm__ __volatile__("enclu\n\t" \ + : "=a" (retval), "=c" (c) \ + : "a" (leaf), "b" (b) \ + : "cc") + +#define __enclu_generic(leaf, b, c, d, retval) \ + __asm__ __volatile__("enclu\n\t" \ + : "=a" (retval), "=b" (b), "=c" (c), "=d" (d)\ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +#define __enclv_bc(leaf, b, c, retval) \ + __asm__ __volatile__("enclv\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "b" (b), "c" (c) \ + : "cc") + +#define __enclv_cd(leaf, c, d, retval) \ + __asm__ __volatile__("enclv\n\t" \ + : "=a" (retval) \ + : "a" (leaf), "c" (c), "d" (d) \ + : "cc") + +#define __enclv_generic(leaf, b, c, d, retval) \ + __asm__ __volatile__("enclv\n\t" \ + : "=a" (retval), "=b" (b), "=c" (b), "=d" (d)\ + : "a" (leaf), "b" (b), "c" (c), "d" (d) \ + : "cc") + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_encls_u32 (const unsigned int __L, size_t __D[]) +{ + enum __encls_type + { + __SGX_ECREATE = 0x00, + __SGX_EADD = 0x01, + __SGX_EINIT = 0x02, + __SGX_EREMOVE = 0x03, + __SGX_EDBGRD = 0x04, + __SGX_EDBGWR = 0x05, + __SGX_EEXTEND = 0x06, + __SGX_ELDB = 0x07, + __SGX_ELDU = 0x08, + __SGX_EBLOCK = 0x09, + __SGX_EPA = 0x0A, + __SGX_EWB = 0x0B, + __SGX_ETRACK = 0x0C, + __SGX_EAUG = 0x0D, + __SGX_EMODPR = 0x0E, + __SGX_EMODT = 0x0F, + __SGX_ERDINFO = 0x10, + __SGX_ETRACKC = 0x11, + __SGX_ELDBC = 0x12, + __SGX_ELDUC = 0x13 + }; + enum __encls_type __T = (enum __encls_type)__L; + unsigned int __R = 0; + if (!__builtin_constant_p (__T)) + __encls_generic (__L, __D[0], __D[1], __D[2], __R); + else switch (__T) + { + case __SGX_ECREATE: + case __SGX_EADD: + case __SGX_EDBGWR: + case __SGX_EEXTEND: + case __SGX_EPA: + case __SGX_EMODPR: + case __SGX_EMODT: + case __SGX_EAUG: + case __SGX_ERDINFO: + __encls_bc (__L, __D[0], __D[1], __R); + break; + case __SGX_EINIT: + case __SGX_ELDB: + case __SGX_ELDU: + case __SGX_EWB: + case __SGX_ELDBC: + case __SGX_ELDUC: + __encls_bcd (__L, __D[0], __D[1], __D[2], __R); + break; + case __SGX_EREMOVE: + case __SGX_EBLOCK: + case __SGX_ETRACK: + case __SGX_ETRACKC: + __encls_c (__L, __D[1], __R); + break; + case __SGX_EDBGRD: + __encls_edbgrd (__L, __D[0], __D[1], __R); + break; + default: + __encls_generic (__L, __D[0], __D[1], __D[2], __R); + } + return __R; +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_enclu_u32 (const unsigned int __L, size_t __D[]) +{ + enum __enclu_type + { + __SGX_EREPORT = 0x00, + __SGX_EGETKEY = 0x01, + __SGX_EENTER = 0x02, + __SGX_ERESUME = 0x03, + __SGX_EEXIT = 0x04, + __SGX_EACCEPT = 0x05, + __SGX_EMODPE = 0x06, + __SGX_EACCEPTCOPY = 0x07 + }; + enum __enclu_type __T = (enum __enclu_type) __L; + unsigned int __R = 0; + if (!__builtin_constant_p (__T)) + __enclu_generic (__L, __D[0], __D[1], __D[2], __R); + else switch (__T) + { + case __SGX_EREPORT: + case __SGX_EACCEPTCOPY: + __enclu_bcd (__L, __D[0], __D[1], __D[2], __R); + break; + case __SGX_EGETKEY: + case __SGX_ERESUME: + case __SGX_EACCEPT: + case __SGX_EMODPE: + __enclu_bc (__L, __D[0], __D[1], __R); + break; + case __SGX_EENTER: + __enclu_eenter (__L, __D[0], __D[1], __R); + break; + case __SGX_EEXIT: + __enclu_eexit (__L, __D[0], __D[1], __R); + break; + default: + __enclu_generic (__L, __D[0], __D[1], __D[2], __R); + } + return __R; +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_enclv_u32 (const unsigned int __L, size_t __D[]) +{ + enum __enclv_type + { + __SGX_EDECVIRTCHILD = 0x00, + __SGX_EINCVIRTCHILD = 0x01, + __SGX_ESETCONTEXT = 0x02 + }; + unsigned int __R = 0; + if (!__builtin_constant_p (__L)) + __enclv_generic (__L, __D[0], __D[1], __D[2], __R); + else switch (__L) + { + case __SGX_EDECVIRTCHILD: + case __SGX_EINCVIRTCHILD: + __enclv_bc (__L, __D[0], __D[1], __R); + break; + case __SGX_ESETCONTEXT: + __enclv_cd (__L, __D[1], __D[2], __R); + break; + default: + __enclv_generic (__L, __D[0], __D[1], __D[2], __R); + } + return __R; +} + +#ifdef __DISABLE_SGX__ +#undef __DISABLE_SGX__ +#pragma GCC pop_options +#endif /* __DISABLE_SGX__ */ + +#endif /* _SGXINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/sha512intrin.h b/template/sysroot/include/sha512intrin.h new file mode 100644 index 0000000..b6816b7 --- /dev/null +++ b/template/sysroot/include/sha512intrin.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _SHA512INTRIN_H_INCLUDED +#define _SHA512INTRIN_H_INCLUDED + +#ifndef __SHA512__ +#pragma GCC push_options +#pragma GCC target("sha512") +#define __DISABLE_SHA512__ +#endif /* __SHA512__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sha512msg1_epi64 (__m256i __A, __m128i __B) +{ + return (__m256i) __builtin_ia32_vsha512msg1 ((__v4di) __A, (__v2di) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sha512msg2_epi64 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_vsha512msg2 ((__v4di) __A, (__v4di) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sha512rnds2_epi64 (__m256i __A, __m256i __B, __m128i __C) +{ + return (__m256i) __builtin_ia32_vsha512rnds2 ((__v4di) __A, (__v4di) __B, + (__v2di) __C); +} + +#ifdef __DISABLE_SHA512__ +#undef __DISABLE_SHA512__ +#pragma GCC pop_options +#endif /* __DISABLE_SHA512__ */ + +#endif /* _SHA512INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/shaintrin.h b/template/sysroot/include/shaintrin.h new file mode 100644 index 0000000..c122988 --- /dev/null +++ b/template/sysroot/include/shaintrin.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _SHAINTRIN_H_INCLUDED +#define _SHAINTRIN_H_INCLUDED + +#ifndef __SHA__ +#pragma GCC push_options +#pragma GCC target("sha") +#define __DISABLE_SHA__ +#endif /* __SHA__ */ + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha1msg1_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_sha1msg1 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha1msg2_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_sha1msg2 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha1nexte_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_sha1nexte ((__v4si) __A, (__v4si) __B); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha1rnds4_epu32 (__m128i __A, __m128i __B, const int __I) +{ + return (__m128i) __builtin_ia32_sha1rnds4 ((__v4si) __A, (__v4si) __B, __I); +} +#else +#define _mm_sha1rnds4_epu32(A, B, I) \ + ((__m128i) __builtin_ia32_sha1rnds4 ((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B), (int)(I))) +#endif + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha256msg1_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_sha256msg1 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha256msg2_epu32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_sha256msg2 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m128i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha256rnds2_epu32 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_sha256rnds2 ((__v4si) __A, (__v4si) __B, + (__v4si) __C); +} + +#ifdef __DISABLE_SHA__ +#undef __DISABLE_SHA__ +#pragma GCC pop_options +#endif /* __DISABLE_SHA__ */ + +#endif /* _SHAINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/sm3intrin.h b/template/sysroot/include/sm3intrin.h new file mode 100644 index 0000000..7f7fc1e --- /dev/null +++ b/template/sysroot/include/sm3intrin.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _SM3INTRIN_H_INCLUDED +#define _SM3INTRIN_H_INCLUDED + +#ifndef __SM3__ +#pragma GCC push_options +#pragma GCC target("sm3") +#define __DISABLE_SM3__ +#endif /* __SM3__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sm3msg1_epi32 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vsm3msg1 ((__v4si) __A, (__v4si) __B, + (__v4si) __C); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sm3msg2_epi32 (__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vsm3msg2 ((__v4si) __A, (__v4si) __B, + (__v4si) __C); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sm3rnds2_epi32 (__m128i __A, __m128i __B, __m128i __C, const int __D) +{ + return (__m128i) __builtin_ia32_vsm3rnds2 ((__v4si) __A, (__v4si) __B, + (__v4si) __C, __D); +} +#else +#define _mm_sm3rnds2_epi32(A, B, C, D) \ + ((__m128i) __builtin_ia32_vsm3rnds2 ((__v4si) (A), (__v4si) (B), \ + (__v4si) (C), (int) (D))) +#endif + +#ifdef __DISABLE_SM3__ +#undef __DISABLE_SM3__ +#pragma GCC pop_options +#endif /* __DISABLE_SM3__ */ + +#endif /* _SM3INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/sm4intrin.h b/template/sysroot/include/sm4intrin.h new file mode 100644 index 0000000..4c212cc --- /dev/null +++ b/template/sysroot/include/sm4intrin.h @@ -0,0 +1,70 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _SM4INTRIN_H_INCLUDED +#define _SM4INTRIN_H_INCLUDED + +#ifndef __SM4__ +#pragma GCC push_options +#pragma GCC target("sm4") +#define __DISABLE_SM4__ +#endif /* __SM4__ */ + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sm4key4_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vsm4key4128 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sm4key4_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_vsm4key4256 ((__v8si) __A, (__v8si) __B); +} + +extern __inline __m128i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sm4rnds4_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vsm4rnds4128 ((__v4si) __A, (__v4si) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_sm4rnds4_epi32 (__m256i __A, __m256i __B) +{ + return (__m256i) __builtin_ia32_vsm4rnds4256 ((__v8si) __A, (__v8si) __B); +} + +#ifdef __DISABLE_SM4__ +#undef __DISABLE_SM4__ +#pragma GCC pop_options +#endif /* __DISABLE_SM4__ */ + +#endif /* _SM4INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/smmintrin.h b/template/sysroot/include/smmintrin.h new file mode 100644 index 0000000..4c315fe --- /dev/null +++ b/template/sysroot/include/smmintrin.h @@ -0,0 +1,852 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 10.0. */ + +#ifndef _SMMINTRIN_H_INCLUDED +#define _SMMINTRIN_H_INCLUDED + +/* We need definitions from the SSSE3, SSE3, SSE2 and SSE header + files. */ +#include + +#ifndef __SSE4_1__ +#pragma GCC push_options +#pragma GCC target("sse4.1") +#define __DISABLE_SSE4_1__ +#endif /* __SSE4_1__ */ + +/* Rounding mode macros. */ +#define _MM_FROUND_TO_NEAREST_INT 0x00 +#define _MM_FROUND_TO_NEG_INF 0x01 +#define _MM_FROUND_TO_POS_INF 0x02 +#define _MM_FROUND_TO_ZERO 0x03 +#define _MM_FROUND_CUR_DIRECTION 0x04 + +#define _MM_FROUND_RAISE_EXC 0x00 +#define _MM_FROUND_NO_EXC 0x08 + +#define _MM_FROUND_NINT \ + (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_RAISE_EXC) +#define _MM_FROUND_FLOOR \ + (_MM_FROUND_TO_NEG_INF | _MM_FROUND_RAISE_EXC) +#define _MM_FROUND_CEIL \ + (_MM_FROUND_TO_POS_INF | _MM_FROUND_RAISE_EXC) +#define _MM_FROUND_TRUNC \ + (_MM_FROUND_TO_ZERO | _MM_FROUND_RAISE_EXC) +#define _MM_FROUND_RINT \ + (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_RAISE_EXC) +#define _MM_FROUND_NEARBYINT \ + (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC) + +/* Test Instruction */ +/* Packed integer 128-bit bitwise comparison. Return 1 if + (__V & __M) == 0. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testz_si128 (__m128i __M, __m128i __V) +{ + return __builtin_ia32_ptestz128 ((__v2di)__M, (__v2di)__V); +} + +/* Packed integer 128-bit bitwise comparison. Return 1 if + (__V & ~__M) == 0. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testc_si128 (__m128i __M, __m128i __V) +{ + return __builtin_ia32_ptestc128 ((__v2di)__M, (__v2di)__V); +} + +/* Packed integer 128-bit bitwise comparison. Return 1 if + (__V & __M) != 0 && (__V & ~__M) != 0. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_testnzc_si128 (__m128i __M, __m128i __V) +{ + return __builtin_ia32_ptestnzc128 ((__v2di)__M, (__v2di)__V); +} + +/* Macros for packed integer 128-bit comparison intrinsics. */ +#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V)) + +#define _mm_test_all_ones(V) \ + _mm_testc_si128 ((V), _mm_cmpeq_epi32 ((V), (V))) + +#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128 ((M), (V)) + +/* Packed/scalar double precision floating point rounding. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_round_pd (__m128d __V, const int __M) +{ + return (__m128d) __builtin_ia32_roundpd ((__v2df)__V, __M); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_round_sd(__m128d __D, __m128d __V, const int __M) +{ + return (__m128d) __builtin_ia32_roundsd ((__v2df)__D, + (__v2df)__V, + __M); +} +#else +#define _mm_round_pd(V, M) \ + ((__m128d) __builtin_ia32_roundpd ((__v2df)(__m128d)(V), (int)(M))) + +#define _mm_round_sd(D, V, M) \ + ((__m128d) __builtin_ia32_roundsd ((__v2df)(__m128d)(D), \ + (__v2df)(__m128d)(V), (int)(M))) +#endif + +/* Packed/scalar single precision floating point rounding. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_round_ps (__m128 __V, const int __M) +{ + return (__m128) __builtin_ia32_roundps ((__v4sf)__V, __M); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_round_ss (__m128 __D, __m128 __V, const int __M) +{ + return (__m128) __builtin_ia32_roundss ((__v4sf)__D, + (__v4sf)__V, + __M); +} +#else +#define _mm_round_ps(V, M) \ + ((__m128) __builtin_ia32_roundps ((__v4sf)(__m128)(V), (int)(M))) + +#define _mm_round_ss(D, V, M) \ + ((__m128) __builtin_ia32_roundss ((__v4sf)(__m128)(D), \ + (__v4sf)(__m128)(V), (int)(M))) +#endif + +/* Macros for ceil/floor intrinsics. */ +#define _mm_ceil_pd(V) _mm_round_pd ((V), _MM_FROUND_CEIL) +#define _mm_ceil_sd(D, V) _mm_round_sd ((D), (V), _MM_FROUND_CEIL) + +#define _mm_floor_pd(V) _mm_round_pd((V), _MM_FROUND_FLOOR) +#define _mm_floor_sd(D, V) _mm_round_sd ((D), (V), _MM_FROUND_FLOOR) + +#define _mm_ceil_ps(V) _mm_round_ps ((V), _MM_FROUND_CEIL) +#define _mm_ceil_ss(D, V) _mm_round_ss ((D), (V), _MM_FROUND_CEIL) + +#define _mm_floor_ps(V) _mm_round_ps ((V), _MM_FROUND_FLOOR) +#define _mm_floor_ss(D, V) _mm_round_ss ((D), (V), _MM_FROUND_FLOOR) + +/* SSE4.1 */ + +/* Integer blend instructions - select data from 2 sources using + constant/variable mask. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blend_epi16 (__m128i __X, __m128i __Y, const int __M) +{ + return (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__X, + (__v8hi)__Y, + __M); +} +#else +#define _mm_blend_epi16(X, Y, M) \ + ((__m128i) __builtin_ia32_pblendw128 ((__v8hi)(__m128i)(X), \ + (__v8hi)(__m128i)(Y), (int)(M))) +#endif + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blendv_epi8 (__m128i __X, __m128i __Y, __m128i __M) +{ + return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__X, + (__v16qi)__Y, + (__v16qi)__M); +} + +/* Single precision floating point blend instructions - select data + from 2 sources using constant/variable mask. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blend_ps (__m128 __X, __m128 __Y, const int __M) +{ + return (__m128) __builtin_ia32_blendps ((__v4sf)__X, + (__v4sf)__Y, + __M); +} +#else +#define _mm_blend_ps(X, Y, M) \ + ((__m128) __builtin_ia32_blendps ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(M))) +#endif + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blendv_ps (__m128 __X, __m128 __Y, __m128 __M) +{ + return (__m128) __builtin_ia32_blendvps ((__v4sf)__X, + (__v4sf)__Y, + (__v4sf)__M); +} + +/* Double precision floating point blend instructions - select data + from 2 sources using constant/variable mask. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blend_pd (__m128d __X, __m128d __Y, const int __M) +{ + return (__m128d) __builtin_ia32_blendpd ((__v2df)__X, + (__v2df)__Y, + __M); +} +#else +#define _mm_blend_pd(X, Y, M) \ + ((__m128d) __builtin_ia32_blendpd ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(M))) +#endif + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blendv_pd (__m128d __X, __m128d __Y, __m128d __M) +{ + return (__m128d) __builtin_ia32_blendvpd ((__v2df)__X, + (__v2df)__Y, + (__v2df)__M); +} + +/* Dot product instructions with mask-defined summing and zeroing parts + of result. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dp_ps (__m128 __X, __m128 __Y, const int __M) +{ + return (__m128) __builtin_ia32_dpps ((__v4sf)__X, + (__v4sf)__Y, + __M); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_dp_pd (__m128d __X, __m128d __Y, const int __M) +{ + return (__m128d) __builtin_ia32_dppd ((__v2df)__X, + (__v2df)__Y, + __M); +} +#else +#define _mm_dp_ps(X, Y, M) \ + ((__m128) __builtin_ia32_dpps ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), (int)(M))) + +#define _mm_dp_pd(X, Y, M) \ + ((__m128d) __builtin_ia32_dppd ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), (int)(M))) +#endif + +/* Packed integer 64-bit comparison, zeroing or filling with ones + corresponding parts of result. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_epi64 (__m128i __X, __m128i __Y) +{ + return (__m128i) ((__v2di)__X == (__v2di)__Y); +} + +/* Min/max packed integer instructions. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminsb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epu16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminuw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epu16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminsd128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_epu32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pminud128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_epu32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaxud128 ((__v4si)__X, (__v4si)__Y); +} + +/* Packed integer 32-bit multiplication with truncation of upper + halves of results. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mullo_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) ((__v4su)__X * (__v4su)__Y); +} + +/* Packed integer 32-bit multiplication of 2 pairs of operands + with two 64-bit results. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmuldq128 ((__v4si)__X, (__v4si)__Y); +} + +/* Insert single precision float into packed single precision array + element selected by index N. The bits [7-6] of N define S + index, the bits [5-4] define D index, and bits [3-0] define + zeroing mask for D. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_ps (__m128 __D, __m128 __S, const int __N) +{ + return (__m128) __builtin_ia32_insertps128 ((__v4sf)__D, + (__v4sf)__S, + __N); +} +#else +#define _mm_insert_ps(D, S, N) \ + ((__m128) __builtin_ia32_insertps128 ((__v4sf)(__m128)(D), \ + (__v4sf)(__m128)(S), (int)(N))) +#endif + +/* Helper macro to create the N value for _mm_insert_ps. */ +#define _MM_MK_INSERTPS_NDX(S, D, M) (((S) << 6) | ((D) << 4) | (M)) + +/* Extract binary representation of single precision float from packed + single precision array element of X selected by index N. */ + +#ifdef __OPTIMIZE__ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_ps (__m128 __X, const int __N) +{ + union { int __i; float __f; } __tmp; + __tmp.__f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N); + return __tmp.__i; +} +#else +#define _mm_extract_ps(X, N) \ + (__extension__ \ + ({ \ + union { int __i; float __f; } __tmp; \ + __tmp.__f = __builtin_ia32_vec_ext_v4sf ((__v4sf)(__m128)(X), \ + (int)(N)); \ + __tmp.__i; \ + })) +#endif + +/* Extract binary representation of single precision float into + D from packed single precision array element of S selected + by index N. */ +#define _MM_EXTRACT_FLOAT(D, S, N) \ + { (D) = __builtin_ia32_vec_ext_v4sf ((__v4sf)(S), (N)); } + +/* Extract specified single precision float element into the lower + part of __m128. */ +#define _MM_PICK_OUT_PS(X, N) \ + _mm_insert_ps (_mm_setzero_ps (), (X), \ + _MM_MK_INSERTPS_NDX ((N), 0, 0x0e)) + +/* Insert integer, S, into packed integer array element of D + selected by index N. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_epi8 (__m128i __D, int __S, const int __N) +{ + return (__m128i) __builtin_ia32_vec_set_v16qi ((__v16qi)__D, + __S, __N); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_epi32 (__m128i __D, int __S, const int __N) +{ + return (__m128i) __builtin_ia32_vec_set_v4si ((__v4si)__D, + __S, __N); +} + +#ifdef __x86_64__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_epi64 (__m128i __D, long long __S, const int __N) +{ + return (__m128i) __builtin_ia32_vec_set_v2di ((__v2di)__D, + __S, __N); +} +#endif +#else +#define _mm_insert_epi8(D, S, N) \ + ((__m128i) __builtin_ia32_vec_set_v16qi ((__v16qi)(__m128i)(D), \ + (int)(S), (int)(N))) + +#define _mm_insert_epi32(D, S, N) \ + ((__m128i) __builtin_ia32_vec_set_v4si ((__v4si)(__m128i)(D), \ + (int)(S), (int)(N))) + +#ifdef __x86_64__ +#define _mm_insert_epi64(D, S, N) \ + ((__m128i) __builtin_ia32_vec_set_v2di ((__v2di)(__m128i)(D), \ + (long long)(S), (int)(N))) +#endif +#endif + +/* Extract integer from packed integer array element of X selected by + index N. */ + +#ifdef __OPTIMIZE__ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_epi8 (__m128i __X, const int __N) +{ + return (unsigned char) __builtin_ia32_vec_ext_v16qi ((__v16qi)__X, __N); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_epi32 (__m128i __X, const int __N) +{ + return __builtin_ia32_vec_ext_v4si ((__v4si)__X, __N); +} + +#ifdef __x86_64__ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_epi64 (__m128i __X, const int __N) +{ + return __builtin_ia32_vec_ext_v2di ((__v2di)__X, __N); +} +#endif +#else +#define _mm_extract_epi8(X, N) \ + ((int) (unsigned char) __builtin_ia32_vec_ext_v16qi ((__v16qi)(__m128i)(X), (int)(N))) +#define _mm_extract_epi32(X, N) \ + ((int) __builtin_ia32_vec_ext_v4si ((__v4si)(__m128i)(X), (int)(N))) + +#ifdef __x86_64__ +#define _mm_extract_epi64(X, N) \ + ((long long) __builtin_ia32_vec_ext_v2di ((__v2di)(__m128i)(X), (int)(N))) +#endif +#endif + +/* Return horizontal packed word minimum and its index in bits [15:0] + and bits [18:16] respectively. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_minpos_epu16 (__m128i __X) +{ + return (__m128i) __builtin_ia32_phminposuw128 ((__v8hi)__X); +} + +/* Packed integer sign-extension. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi8_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxbd128 ((__v16qi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi16_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxwd128 ((__v8hi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi8_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxbq128 ((__v16qi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi32_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxdq128 ((__v4si)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi16_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxwq128 ((__v8hi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepi8_epi16 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovsxbw128 ((__v16qi)__X); +} + +/* Packed integer zero-extension. */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu8_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxbd128 ((__v16qi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu16_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxwd128 ((__v8hi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu8_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxbq128 ((__v16qi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu32_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxdq128 ((__v4si)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu16_epi64 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxwq128 ((__v8hi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtepu8_epi16 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pmovzxbw128 ((__v16qi)__X); +} + +/* Pack 8 double words from 2 operands into 8 words of result with + unsigned saturation. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packus_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_packusdw128 ((__v4si)__X, (__v4si)__Y); +} + +/* Sum absolute 8-bit integer difference of adjacent groups of 4 + byte integers in the first 2 operands. Starting offsets within + operands are determined by the 3rd mask operand. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mpsadbw_epu8 (__m128i __X, __m128i __Y, const int __M) +{ + return (__m128i) __builtin_ia32_mpsadbw128 ((__v16qi)__X, + (__v16qi)__Y, __M); +} +#else +#define _mm_mpsadbw_epu8(X, Y, M) \ + ((__m128i) __builtin_ia32_mpsadbw128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#endif + +/* Load double quadword using non-temporal aligned hint. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_load_si128 (__m128i *__X) +{ + return (__m128i) __builtin_ia32_movntdqa ((__v2di *) __X); +} + +#ifndef __SSE4_2__ +#pragma GCC push_options +#pragma GCC target("sse4.2") +#define __DISABLE_SSE4_2__ +#endif /* __SSE4_2__ */ + +/* These macros specify the source data format. */ +#define _SIDD_UBYTE_OPS 0x00 +#define _SIDD_UWORD_OPS 0x01 +#define _SIDD_SBYTE_OPS 0x02 +#define _SIDD_SWORD_OPS 0x03 + +/* These macros specify the comparison operation. */ +#define _SIDD_CMP_EQUAL_ANY 0x00 +#define _SIDD_CMP_RANGES 0x04 +#define _SIDD_CMP_EQUAL_EACH 0x08 +#define _SIDD_CMP_EQUAL_ORDERED 0x0c + +/* These macros specify the polarity. */ +#define _SIDD_POSITIVE_POLARITY 0x00 +#define _SIDD_NEGATIVE_POLARITY 0x10 +#define _SIDD_MASKED_POSITIVE_POLARITY 0x20 +#define _SIDD_MASKED_NEGATIVE_POLARITY 0x30 + +/* These macros specify the output selection in _mm_cmpXstri (). */ +#define _SIDD_LEAST_SIGNIFICANT 0x00 +#define _SIDD_MOST_SIGNIFICANT 0x40 + +/* These macros specify the output selection in _mm_cmpXstrm (). */ +#define _SIDD_BIT_MASK 0x00 +#define _SIDD_UNIT_MASK 0x40 + +/* Intrinsics for text/string processing. */ + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistrm (__m128i __X, __m128i __Y, const int __M) +{ + return (__m128i) __builtin_ia32_pcmpistrm128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistri (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistri128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestrm (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return (__m128i) __builtin_ia32_pcmpestrm128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestri (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestri128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} +#else +#define _mm_cmpistrm(X, Y, M) \ + ((__m128i) __builtin_ia32_pcmpistrm128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#define _mm_cmpistri(X, Y, M) \ + ((int) __builtin_ia32_pcmpistri128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) + +#define _mm_cmpestrm(X, LX, Y, LY, M) \ + ((__m128i) __builtin_ia32_pcmpestrm128 ((__v16qi)(__m128i)(X), \ + (int)(LX), (__v16qi)(__m128i)(Y), \ + (int)(LY), (int)(M))) +#define _mm_cmpestri(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestri128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#endif + +/* Intrinsics for text/string processing and reading values of + EFlags. */ + +#ifdef __OPTIMIZE__ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistra (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistria128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistrc (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistric128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistro (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistrio128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistrs (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistris128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpistrz (__m128i __X, __m128i __Y, const int __M) +{ + return __builtin_ia32_pcmpistriz128 ((__v16qi)__X, + (__v16qi)__Y, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestra (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestria128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestrc (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestric128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestro (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestrio128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestrs (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestris128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpestrz (__m128i __X, int __LX, __m128i __Y, int __LY, const int __M) +{ + return __builtin_ia32_pcmpestriz128 ((__v16qi)__X, __LX, + (__v16qi)__Y, __LY, + __M); +} +#else +#define _mm_cmpistra(X, Y, M) \ + ((int) __builtin_ia32_pcmpistria128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#define _mm_cmpistrc(X, Y, M) \ + ((int) __builtin_ia32_pcmpistric128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#define _mm_cmpistro(X, Y, M) \ + ((int) __builtin_ia32_pcmpistrio128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#define _mm_cmpistrs(X, Y, M) \ + ((int) __builtin_ia32_pcmpistris128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) +#define _mm_cmpistrz(X, Y, M) \ + ((int) __builtin_ia32_pcmpistriz128 ((__v16qi)(__m128i)(X), \ + (__v16qi)(__m128i)(Y), (int)(M))) + +#define _mm_cmpestra(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestria128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#define _mm_cmpestrc(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestric128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#define _mm_cmpestro(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestrio128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#define _mm_cmpestrs(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestris128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#define _mm_cmpestrz(X, LX, Y, LY, M) \ + ((int) __builtin_ia32_pcmpestriz128 ((__v16qi)(__m128i)(X), (int)(LX), \ + (__v16qi)(__m128i)(Y), (int)(LY), \ + (int)(M))) +#endif + +/* Packed integer 64-bit comparison, zeroing or filling with ones + corresponding parts of result. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_epi64 (__m128i __X, __m128i __Y) +{ + return (__m128i) ((__v2di)__X > (__v2di)__Y); +} + +#ifdef __DISABLE_SSE4_2__ +#undef __DISABLE_SSE4_2__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE4_2__ */ + +#ifdef __DISABLE_SSE4_1__ +#undef __DISABLE_SSE4_1__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE4_1__ */ + +#include + +#ifndef __CRC32__ +#pragma GCC push_options +#pragma GCC target("crc32") +#define __DISABLE_CRC32__ +#endif /* __CRC32__ */ + +/* Accumulate CRC32 (polynomial 0x11EDC6F41) value. */ +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_crc32_u8 (unsigned int __C, unsigned char __V) +{ + return __builtin_ia32_crc32qi (__C, __V); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_crc32_u16 (unsigned int __C, unsigned short __V) +{ + return __builtin_ia32_crc32hi (__C, __V); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_crc32_u32 (unsigned int __C, unsigned int __V) +{ + return __builtin_ia32_crc32si (__C, __V); +} + +#ifdef __x86_64__ +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_crc32_u64 (unsigned long long __C, unsigned long long __V) +{ + return __builtin_ia32_crc32di (__C, __V); +} +#endif + +#ifdef __DISABLE_CRC32__ +#undef __DISABLE_CRC32__ +#pragma GCC pop_options +#endif /* __DISABLE_CRC32__ */ + +#endif /* _SMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/source_location b/template/sysroot/include/source_location new file mode 100644 index 0000000..d2a2ed1 --- /dev/null +++ b/template/sysroot/include/source_location @@ -0,0 +1,93 @@ +// -*- C++ -*- + +// Copyright (C) 2020-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/source_location + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SRCLOC +#define _GLIBCXX_SRCLOC 1 + +#define __glibcxx_want_source_location +#include + +#if __cpp_lib_source_location // C++ >= 20 && builtin_source_location +#include + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// A class that describes a location in source code. + struct source_location + { + private: + using uint_least32_t = __UINT_LEAST32_TYPE__; + struct __impl + { + const char* _M_file_name; + const char* _M_function_name; + unsigned _M_line; + unsigned _M_column; + }; + using __builtin_ret_type = decltype(__builtin_source_location()); + + public: + + // [support.srcloc.cons], creation + static consteval source_location + current(__builtin_ret_type __p = __builtin_source_location()) noexcept + { + source_location __ret; + __ret._M_impl = static_cast (__p); + return __ret; + } + + constexpr source_location() noexcept { } + + // [support.srcloc.obs], observers + constexpr uint_least32_t + line() const noexcept + { return _M_impl ? _M_impl->_M_line : 0u; } + + constexpr uint_least32_t + column() const noexcept + { return _M_impl ? _M_impl->_M_column : 0u; } + + constexpr const char* + file_name() const noexcept + { return _M_impl ? _M_impl->_M_file_name : ""; } + + constexpr const char* + function_name() const noexcept + { return _M_impl ? _M_impl->_M_function_name : ""; } + + private: + const __impl* _M_impl = nullptr; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __cpp_lib_source_location +#endif // _GLIBCXX_SRCLOC diff --git a/template/sysroot/include/span b/template/sysroot/include/span new file mode 100644 index 0000000..00fc527 --- /dev/null +++ b/template/sysroot/include/span @@ -0,0 +1,512 @@ +// Components for manipulating non-owning sequences of objects -*- C++ -*- + +// Copyright (C) 2019-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file span + * This is a Standard C++ Library header. + */ + +// +// P0122 span library +// Contributed by ThePhD +// + +#ifndef _GLIBCXX_SPAN +#define _GLIBCXX_SPAN 1 + +#pragma GCC system_header + +#define __glibcxx_want_span +#include + +#ifdef __cpp_lib_span // C++ >= 20 && concepts +#include +#include +#include +#include +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + inline constexpr size_t dynamic_extent = static_cast(-1); + + template + class span; + + namespace __detail + { + template + inline constexpr bool __is_span = false; + + template + inline constexpr bool __is_span> = true; + + template + inline constexpr bool __is_std_array = false; + + template + inline constexpr bool __is_std_array> = true; + + template + class __extent_storage + { + public: + constexpr + __extent_storage(size_t) noexcept + { } + + static constexpr size_t + _M_extent() noexcept + { return _Extent; } + }; + + template<> + class __extent_storage + { + public: + constexpr + __extent_storage(size_t __extent) noexcept + : _M_extent_value(__extent) + { } + + constexpr size_t + _M_extent() const noexcept + { return this->_M_extent_value; } + + private: + size_t _M_extent_value; + }; + } // namespace __detail + + template + class span + { + template + static constexpr size_t + _S_subspan_extent() + { + if constexpr (_Count != dynamic_extent) + return _Count; + else if constexpr (extent != dynamic_extent) + return _Extent - _Offset; + else + return dynamic_extent; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3255. span's array constructor is too strict + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + using __is_compatible_array = __is_array_convertible<_Type, _Tp>; + + template + using __is_compatible_ref + = __is_array_convertible<_Type, remove_reference_t<_Ref>>; + + public: + // member types + using element_type = _Type; + using value_type = remove_cv_t<_Type>; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = _Type*; + using const_pointer = const _Type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = __gnu_cxx::__normal_iterator; + using reverse_iterator = std::reverse_iterator; +#if __cplusplus > 202002L + using const_iterator = std::const_iterator; + using const_reverse_iterator = std::const_iterator; +#endif + + // member constants + static constexpr size_t extent = _Extent; + + // constructors, copy and assignment + + constexpr + span() noexcept + requires (_Extent == dynamic_extent || _Extent == 0) + : _M_ptr(nullptr), _M_extent(0) + { } + + template + requires __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_It __first, size_type __count) + noexcept + : _M_ptr(std::to_address(__first)), _M_extent(__count) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert(__count == _Extent); + } + __glibcxx_requires_valid_range(__first, __first + __count); + } + + template _End> + requires __is_compatible_ref>::value + && (!is_convertible_v<_End, size_type>) + constexpr explicit(extent != dynamic_extent) + span(_It __first, _End __last) + noexcept(noexcept(__last - __first)) + : _M_ptr(std::to_address(__first)), + _M_extent(static_cast(__last - __first)) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert((__last - __first) == _Extent); + } + __glibcxx_requires_valid_range(__first, __last); + } + + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + constexpr + span(type_identity_t (&__arr)[_ArrayExtent]) noexcept + : span(static_cast(__arr), _ArrayExtent) + { } + + template + requires __is_compatible_array<_Tp, _ArrayExtent>::value + constexpr + span(array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires __is_compatible_array::value + constexpr + span(const array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires (!__detail::__is_span>) + && (!__detail::__is_std_array>) + && (!is_array_v>) + && ranges::contiguous_range<_Range> && ranges::sized_range<_Range> + && (ranges::borrowed_range<_Range> || is_const_v) + && __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_Range&& __range) + noexcept(noexcept(ranges::data(__range)) + && noexcept(ranges::size(__range))) + : span(ranges::data(__range), ranges::size(__range)) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(ranges::size(__range) == extent); + } + } + + constexpr + span(const span&) noexcept = default; + + template + requires (_Extent == dynamic_extent || _OExtent == dynamic_extent + || _Extent == _OExtent) + && (__is_array_convertible<_Type, _OType>::value) + constexpr + explicit(extent != dynamic_extent && _OExtent == dynamic_extent) + span(const span<_OType, _OExtent>& __s) noexcept + : _M_extent(__s.size()), _M_ptr(__s.data()) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(__s.size() == extent); + } + } + + ~span() noexcept = default; + + constexpr span& + operator=(const span&) noexcept = default; + + // observers + + [[nodiscard]] + constexpr size_type + size() const noexcept + { return this->_M_extent._M_extent(); } + + [[nodiscard]] + constexpr size_type + size_bytes() const noexcept + { return this->_M_extent._M_extent() * sizeof(element_type); } + + [[nodiscard]] + constexpr bool + empty() const noexcept + { return size() == 0; } + + // element access + + [[nodiscard]] + constexpr reference + front() const noexcept + { + __glibcxx_assert(!empty()); + return *this->_M_ptr; + } + + [[nodiscard]] + constexpr reference + back() const noexcept + { + __glibcxx_assert(!empty()); + return *(this->_M_ptr + (size() - 1)); + } + + [[nodiscard]] + constexpr reference + operator[](size_type __idx) const noexcept + { + __glibcxx_assert(__idx < size()); + return *(this->_M_ptr + __idx); + } + +#if __cpp_lib_span >= 202311L // >= C++26 + [[nodiscard]] + constexpr reference + at(size_type __idx) const + { + if (__idx >= size()) + __throw_out_of_range_fmt(__N("span::at(%zu) out-of-range for span " + "of size %zu"), __idx, this->size()); + return *(this->_M_ptr + __idx); + } +#endif + + [[nodiscard]] + constexpr pointer + data() const noexcept + { return this->_M_ptr; } + + // iterator support + + [[nodiscard]] + constexpr iterator + begin() const noexcept + { return iterator(this->_M_ptr); } + + [[nodiscard]] + constexpr iterator + end() const noexcept + { return iterator(this->_M_ptr + this->size()); } + + [[nodiscard]] + constexpr reverse_iterator + rbegin() const noexcept + { return reverse_iterator(this->end()); } + + [[nodiscard]] + constexpr reverse_iterator + rend() const noexcept + { return reverse_iterator(this->begin()); } + +#if __cplusplus > 202002L + [[nodiscard]] + constexpr const_iterator + cbegin() const noexcept + { return begin(); } + + [[nodiscard]] + constexpr const_iterator + cend() const noexcept + { return end(); } + + [[nodiscard]] + constexpr const_reverse_iterator + crbegin() const noexcept + { return rbegin(); } + + [[nodiscard]] + constexpr const_reverse_iterator + crend() const noexcept + { return rend(); } +#endif + + // subviews + + template + [[nodiscard]] + constexpr span + first() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data(), _Count }; + } + + [[nodiscard]] + constexpr span + first(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data(), __count }; + } + + template + [[nodiscard]] + constexpr span + last() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data() + (this->size() - _Count), _Count }; + } + + [[nodiscard]] + constexpr span + last(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data() + (this->size() - __count), __count }; + } + + template + [[nodiscard]] + constexpr auto + subspan() const noexcept + -> span()> + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Offset <= size()); + } + else + static_assert(_Offset <= extent); + + using _Sp = span()>; + + if constexpr (_Count == dynamic_extent) + return _Sp{ this->data() + _Offset, this->size() - _Offset }; + else + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Count <= size()); + __glibcxx_assert(_Count <= (size() - _Offset)); + } + else + { + static_assert(_Count <= extent); + static_assert(_Count <= (extent - _Offset)); + } + return _Sp{ this->data() + _Offset, _Count }; + } + } + + [[nodiscard]] + constexpr span + subspan(size_type __offset, size_type __count = dynamic_extent) const + noexcept + { + __glibcxx_assert(__offset <= size()); + if (__count == dynamic_extent) + __count = this->size() - __offset; + else + { + __glibcxx_assert(__count <= size()); + __glibcxx_assert(__offset + __count <= size()); + } + return {this->data() + __offset, __count}; + } + + private: + pointer _M_ptr; + [[no_unique_address]] __detail::__extent_storage _M_extent; + }; + + // deduction guides + + template + span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; + + template + span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; + + template + span(const array<_Type, _ArrayExtent>&) + -> span; + + template + span(_Iter, _End) + -> span>>; + + template + span(_Range &&) + -> span>>; + + template + [[nodiscard]] + inline + span + as_bytes(span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + template + requires (!is_const_v<_Type>) + inline + span + as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> = true; + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __cpp_lib_span +#endif // _GLIBCXX_SPAN diff --git a/template/sysroot/include/stdalign.h b/template/sysroot/include/stdalign.h new file mode 100644 index 0000000..5f82f2d --- /dev/null +++ b/template/sysroot/include/stdalign.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* ISO C1X: 7.15 Alignment . */ + +#ifndef _STDALIGN_H +#define _STDALIGN_H + +#if (!defined __cplusplus \ + && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)) + +#define alignas _Alignas +#define alignof _Alignof + +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 + +#endif + +#endif /* stdalign.h */ diff --git a/template/sysroot/include/stdarg.h b/template/sysroot/include/stdarg.h new file mode 100644 index 0000000..9c9bc5d --- /dev/null +++ b/template/sysroot/include/stdarg.h @@ -0,0 +1,135 @@ +/* Copyright (C) 1989-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.15 Variable arguments + */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define va_start(v, ...) __builtin_va_start(v, 0) +#else +#define va_start(v,l) __builtin_va_start(v,l) +#endif +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \ + || __cplusplus + 0 >= 201103L +#define va_copy(d,s) __builtin_va_copy(d,s) +#endif +#define __va_copy(d,s) __builtin_va_copy(d,s) + +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +/* The macro __va_list__ is used by BeOS. */ +#ifndef __va_list__ +typedef __gnuc_va_list va_list; +#endif /* not __va_list__ */ +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif +#ifndef __va_list__ +#define __va_list__ +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define __STDC_VERSION_STDARG_H__ 202311L +#endif + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */ diff --git a/template/sysroot/include/stdatomic.h b/template/sysroot/include/stdatomic.h new file mode 100644 index 0000000..3b947eb --- /dev/null +++ b/template/sysroot/include/stdatomic.h @@ -0,0 +1,255 @@ +/* Copyright (C) 2013-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* ISO C11 Standard: 7.17 Atomics . */ + +#ifndef _STDATOMIC_H +#define _STDATOMIC_H + +typedef enum + { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST + } memory_order; + + +typedef _Atomic _Bool atomic_bool; +typedef _Atomic char atomic_char; +typedef _Atomic signed char atomic_schar; +typedef _Atomic unsigned char atomic_uchar; +typedef _Atomic short atomic_short; +typedef _Atomic unsigned short atomic_ushort; +typedef _Atomic int atomic_int; +typedef _Atomic unsigned int atomic_uint; +typedef _Atomic long atomic_long; +typedef _Atomic unsigned long atomic_ulong; +typedef _Atomic long long atomic_llong; +typedef _Atomic unsigned long long atomic_ullong; +#ifdef __CHAR8_TYPE__ +typedef _Atomic __CHAR8_TYPE__ atomic_char8_t; +#endif +typedef _Atomic __CHAR16_TYPE__ atomic_char16_t; +typedef _Atomic __CHAR32_TYPE__ atomic_char32_t; +typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t; +typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t; +typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t; +typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t; +typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t; +typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t; +typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t; +typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t; +typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t; +typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t; +typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t; +typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t; +typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t; +typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t; +typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t; +typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t; +typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t; +typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t; +typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t; +typedef _Atomic __SIZE_TYPE__ atomic_size_t; +typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t; +typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t; +typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t; + + +#if !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) +#define ATOMIC_VAR_INIT(VALUE) (VALUE) +#endif + +/* Initialize an atomic object pointed to by PTR with VAL. */ +#define atomic_init(PTR, VAL) \ + atomic_store_explicit (PTR, VAL, __ATOMIC_RELAXED) + +#define kill_dependency(Y) \ + __extension__ \ + ({ \ + __auto_type __kill_dependency_tmp = (Y); \ + __kill_dependency_tmp; \ + }) + +extern void atomic_thread_fence (memory_order); +#define atomic_thread_fence(MO) __atomic_thread_fence (MO) +extern void atomic_signal_fence (memory_order); +#define atomic_signal_fence(MO) __atomic_signal_fence (MO) +#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ)) + +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#ifdef __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE + + +/* Note that these macros require __auto_type to remove + _Atomic qualifiers (and const qualifiers, if those are valid on + macro operands). + + Also note that the header file uses the generic form of __atomic + builtins, which requires the address to be taken of the value + parameter, and then we pass that value on. This allows the macros + to work for any type, and the compiler is smart enough to convert + these to lock-free _N variants if possible, and throw away the + temps. */ + +#define atomic_store_explicit(PTR, VAL, MO) \ + __extension__ \ + ({ \ + __auto_type __atomic_store_ptr = (PTR); \ + __typeof__ ((void)0, *__atomic_store_ptr) __atomic_store_tmp = (VAL); \ + __atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \ + }) + +#define atomic_store(PTR, VAL) \ + atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST) + + +#define atomic_load_explicit(PTR, MO) \ + __extension__ \ + ({ \ + __auto_type __atomic_load_ptr = (PTR); \ + __typeof__ ((void)0, *__atomic_load_ptr) __atomic_load_tmp; \ + __atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \ + __atomic_load_tmp; \ + }) + +#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST) + + +#define atomic_exchange_explicit(PTR, VAL, MO) \ + __extension__ \ + ({ \ + __auto_type __atomic_exchange_ptr = (PTR); \ + __typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_val = (VAL); \ + __typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_tmp; \ + __atomic_exchange (__atomic_exchange_ptr, &__atomic_exchange_val, \ + &__atomic_exchange_tmp, (MO)); \ + __atomic_exchange_tmp; \ + }) + +#define atomic_exchange(PTR, VAL) \ + atomic_exchange_explicit (PTR, VAL, __ATOMIC_SEQ_CST) + + +#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) \ + __extension__ \ + ({ \ + __auto_type __atomic_compare_exchange_ptr = (PTR); \ + __typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \ + = (DES); \ + __atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \ + &__atomic_compare_exchange_tmp, 0, \ + (SUC), (FAIL)); \ + }) + +#define atomic_compare_exchange_strong(PTR, VAL, DES) \ + atomic_compare_exchange_strong_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \ + __ATOMIC_SEQ_CST) + +#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) \ + __extension__ \ + ({ \ + __auto_type __atomic_compare_exchange_ptr = (PTR); \ + __typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \ + = (DES); \ + __atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \ + &__atomic_compare_exchange_tmp, 1, \ + (SUC), (FAIL)); \ + }) + +#define atomic_compare_exchange_weak(PTR, VAL, DES) \ + atomic_compare_exchange_weak_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \ + __ATOMIC_SEQ_CST) + + + +#define atomic_fetch_add(PTR, VAL) __atomic_fetch_add ((PTR), (VAL), \ + __ATOMIC_SEQ_CST) +#define atomic_fetch_add_explicit(PTR, VAL, MO) \ + __atomic_fetch_add ((PTR), (VAL), (MO)) + +#define atomic_fetch_sub(PTR, VAL) __atomic_fetch_sub ((PTR), (VAL), \ + __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_explicit(PTR, VAL, MO) \ + __atomic_fetch_sub ((PTR), (VAL), (MO)) + +#define atomic_fetch_or(PTR, VAL) __atomic_fetch_or ((PTR), (VAL), \ + __ATOMIC_SEQ_CST) +#define atomic_fetch_or_explicit(PTR, VAL, MO) \ + __atomic_fetch_or ((PTR), (VAL), (MO)) + +#define atomic_fetch_xor(PTR, VAL) __atomic_fetch_xor ((PTR), (VAL), \ + __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_explicit(PTR, VAL, MO) \ + __atomic_fetch_xor ((PTR), (VAL), (MO)) + +#define atomic_fetch_and(PTR, VAL) __atomic_fetch_and ((PTR), (VAL), \ + __ATOMIC_SEQ_CST) +#define atomic_fetch_and_explicit(PTR, VAL, MO) \ + __atomic_fetch_and ((PTR), (VAL), (MO)) + + +typedef _Atomic struct +{ +#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 + _Bool __val; +#else + unsigned char __val; +#endif +} atomic_flag; + +#define ATOMIC_FLAG_INIT { 0 } + + +extern _Bool atomic_flag_test_and_set (volatile atomic_flag *); +#define atomic_flag_test_and_set(PTR) \ + __atomic_test_and_set ((PTR), __ATOMIC_SEQ_CST) +extern _Bool atomic_flag_test_and_set_explicit (volatile atomic_flag *, + memory_order); +#define atomic_flag_test_and_set_explicit(PTR, MO) \ + __atomic_test_and_set ((PTR), (MO)) + +extern void atomic_flag_clear (volatile atomic_flag *); +#define atomic_flag_clear(PTR) __atomic_clear ((PTR), __ATOMIC_SEQ_CST) +extern void atomic_flag_clear_explicit (volatile atomic_flag *, memory_order); +#define atomic_flag_clear_explicit(PTR, MO) __atomic_clear ((PTR), (MO)) + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define __STDC_VERSION_STDATOMIC_H__ 202311L +#endif + +#endif /* _STDATOMIC_H */ diff --git a/template/sysroot/include/stdbool.h b/template/sysroot/include/stdbool.h new file mode 100644 index 0000000..2d2ee29 --- /dev/null +++ b/template/sysroot/include/stdbool.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1998-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.16 Boolean type and values + */ + +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#ifndef __cplusplus + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +/* bool, true and false are keywords. */ +#else +#define bool _Bool +#define true 1 +#define false 0 +#endif + +#else /* __cplusplus */ + +/* Supporting _Bool in C++ is a GCC extension. */ +#define _Bool bool + +#endif /* __cplusplus */ + +/* Signal that all the definitions are present. */ +#define __bool_true_false_are_defined 1 + +#endif /* stdbool.h */ diff --git a/template/sysroot/include/stdckdint.h b/template/sysroot/include/stdckdint.h new file mode 100644 index 0000000..209a738 --- /dev/null +++ b/template/sysroot/include/stdckdint.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* ISO C23: 7.20 Checked Integer Arithmetic . */ + +#ifndef _STDCKDINT_H +#define _STDCKDINT_H + +#define __STDC_VERSION_STDCKDINT_H__ 202311L + +#define ckd_add(r, a, b) ((_Bool) __builtin_add_overflow (a, b, r)) +#define ckd_sub(r, a, b) ((_Bool) __builtin_sub_overflow (a, b, r)) +#define ckd_mul(r, a, b) ((_Bool) __builtin_mul_overflow (a, b, r)) + +/* Allow for the C library to add its part to the header. */ +#if !defined (_LIBC_STDCKDINT_H) && __has_include_next () +# include_next +#endif + +#endif /* stdckdint.h */ diff --git a/template/sysroot/include/stddef.h b/template/sysroot/include/stddef.h new file mode 100644 index 0000000..5b8515d --- /dev/null +++ b/template/sysroot/include/stddef.h @@ -0,0 +1,463 @@ +/* Copyright (C) 1989-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.17 Common definitions + */ +#if (!defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ + && !defined(__STDDEF_H__)) \ + || defined(__need_wchar_t) || defined(__need_size_t) \ + || defined(__need_ptrdiff_t) || defined(__need_NULL) \ + || defined(__need_wint_t) + +/* Any one of these symbols __need_* means that GNU libc + wants us just to define one data type. So don't define + the symbols that indicate this file's entire job has been done. */ +#if (!defined(__need_wchar_t) && !defined(__need_size_t) \ + && !defined(__need_ptrdiff_t) && !defined(__need_NULL) \ + && !defined(__need_wint_t)) +#define _STDDEF_H +#define _STDDEF_H_ +/* snaroff@next.com says the NeXT needs this. */ +#define _ANSI_STDDEF_H +#endif + +#ifndef __sys_stdtypes_h +/* This avoids lossage on SunOS but only if stdtypes.h comes first. + There's no way to win with the other order! Sun lossage. */ + +#if defined(__NetBSD__) +#include +#endif + +#if defined (__FreeBSD__) +#include +#endif + +#if defined(__NetBSD__) +#if !defined(_SIZE_T_) && !defined(_BSD_SIZE_T_) +#define _SIZE_T +#endif +#if !defined(_PTRDIFF_T_) && !defined(_BSD_PTRDIFF_T_) +#define _PTRDIFF_T +#endif +/* On BSD/386 1.1, at least, machine/ansi.h defines _BSD_WCHAR_T_ + instead of _WCHAR_T_. */ +#if !defined(_WCHAR_T_) && !defined(_BSD_WCHAR_T_) +#ifndef _BSD_WCHAR_T_ +#define _WCHAR_T +#endif +#endif +/* Undef _FOO_T_ if we are supposed to define foo_t. */ +#if defined (__need_ptrdiff_t) || defined (_STDDEF_H_) +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#if defined (__need_size_t) || defined (_STDDEF_H_) +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#if defined (__need_wchar_t) || defined (_STDDEF_H_) +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +#endif /* defined(__NetBSD__) */ + +/* Sequent's header files use _PTRDIFF_T_ in some conflicting way. + Just ignore it. */ +#if defined (__sequent__) && defined (_PTRDIFF_T_) +#undef _PTRDIFF_T_ +#endif + +/* On VxWorks, may have defined macros like + _TYPE_size_t which will typedef size_t. fixincludes patched the + vxTypesBase.h so that this macro is only defined if _GCC_SIZE_T is + not defined, and so that defining this macro defines _GCC_SIZE_T. + If we find that the macros are still defined at this point, we must + invoke them so that the type is defined as expected. */ +#if defined (_TYPE_ptrdiff_t) && (defined (__need_ptrdiff_t) || defined (_STDDEF_H_)) +_TYPE_ptrdiff_t; +#undef _TYPE_ptrdiff_t +#endif +#if defined (_TYPE_size_t) && (defined (__need_size_t) || defined (_STDDEF_H_)) +_TYPE_size_t; +#undef _TYPE_size_t +#endif +#if defined (_TYPE_wchar_t) && (defined (__need_wchar_t) || defined (_STDDEF_H_)) +_TYPE_wchar_t; +#undef _TYPE_wchar_t +#endif + +/* In case nobody has defined these types, but we aren't running under + GCC 2.00, make sure that __PTRDIFF_TYPE__, __SIZE_TYPE__, and + __WCHAR_TYPE__ have reasonable values. This can happen if the + parts of GCC is compiled by an older compiler, that actually + include gstddef.h, such as collect2. */ + +/* Signed type of difference of two pointers. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_ptrdiff_t) +#ifndef _PTRDIFF_T /* in case has defined it. */ +#ifndef _T_PTRDIFF_ +#ifndef _T_PTRDIFF +#ifndef __PTRDIFF_T +#ifndef _PTRDIFF_T_ +#ifndef _BSD_PTRDIFF_T_ +#ifndef ___int_ptrdiff_t_h +#ifndef _GCC_PTRDIFF_T +#ifndef _PTRDIFF_T_DECLARED /* DragonFly */ +#ifndef __DEFINED_ptrdiff_t /* musl libc */ +#define _PTRDIFF_T +#define _T_PTRDIFF_ +#define _T_PTRDIFF +#define __PTRDIFF_T +#define _PTRDIFF_T_ +#define _BSD_PTRDIFF_T_ +#define ___int_ptrdiff_t_h +#define _GCC_PTRDIFF_T +#define _PTRDIFF_T_DECLARED +#define __DEFINED_ptrdiff_t +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ long int +#endif +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#endif /* __DEFINED_ptrdiff_t */ +#endif /* _PTRDIFF_T_DECLARED */ +#endif /* _GCC_PTRDIFF_T */ +#endif /* ___int_ptrdiff_t_h */ +#endif /* _BSD_PTRDIFF_T_ */ +#endif /* _PTRDIFF_T_ */ +#endif /* __PTRDIFF_T */ +#endif /* _T_PTRDIFF */ +#endif /* _T_PTRDIFF_ */ +#endif /* _PTRDIFF_T */ + +/* If this symbol has done its job, get rid of it. */ +#undef __need_ptrdiff_t + +#endif /* _STDDEF_H or __need_ptrdiff_t. */ + +/* Unsigned type of `sizeof' something. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_size_t) +#ifndef __size_t__ /* BeOS */ +#ifndef __SIZE_T__ /* Cray Unicos/Mk */ +#ifndef _SIZE_T /* in case has defined it. */ +#ifndef _SYS_SIZE_T_H +#ifndef _T_SIZE_ +#ifndef _T_SIZE +#ifndef __SIZE_T +#ifndef _SIZE_T_ +#ifndef _BSD_SIZE_T_ +#ifndef _SIZE_T_DEFINED_ +#ifndef _SIZE_T_DEFINED +#ifndef _BSD_SIZE_T_DEFINED_ /* Darwin */ +#ifndef _SIZE_T_DECLARED /* FreeBSD 5 */ +#ifndef __DEFINED_size_t /* musl libc */ +#ifndef ___int_size_t_h +#ifndef _GCC_SIZE_T +#ifndef _SIZET_ +#ifndef __size_t +#define __size_t__ /* BeOS */ +#define __SIZE_T__ /* Cray Unicos/Mk */ +#define _SIZE_T +#define _SYS_SIZE_T_H +#define _T_SIZE_ +#define _T_SIZE +#define __SIZE_T +#define _SIZE_T_ +#define _BSD_SIZE_T_ +#define _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED +#define _BSD_SIZE_T_DEFINED_ /* Darwin */ +#define _SIZE_T_DECLARED /* FreeBSD 5 */ +#define __DEFINED_size_t /* musl libc */ +#define ___int_size_t_h +#define _GCC_SIZE_T +#define _SIZET_ +#if defined (__FreeBSD__) \ + || defined(__DragonFly__) \ + || defined(__FreeBSD_kernel__) \ + || defined(__VMS__) +/* __size_t is a typedef, must not trash it. */ +#else +#define __size_t +#endif +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ long unsigned int +#endif +#if !(defined (__GNUG__) && defined (size_t)) +typedef __SIZE_TYPE__ size_t; +#ifdef __BEOS__ +typedef long ssize_t; +#endif /* __BEOS__ */ +#endif /* !(defined (__GNUG__) && defined (size_t)) */ +#endif /* __size_t */ +#endif /* _SIZET_ */ +#endif /* _GCC_SIZE_T */ +#endif /* ___int_size_t_h */ +#endif /* __DEFINED_size_t */ +#endif /* _SIZE_T_DECLARED */ +#endif /* _BSD_SIZE_T_DEFINED_ */ +#endif /* _SIZE_T_DEFINED */ +#endif /* _SIZE_T_DEFINED_ */ +#endif /* _BSD_SIZE_T_ */ +#endif /* _SIZE_T_ */ +#endif /* __SIZE_T */ +#endif /* _T_SIZE */ +#endif /* _T_SIZE_ */ +#endif /* _SYS_SIZE_T_H */ +#endif /* _SIZE_T */ +#endif /* __SIZE_T__ */ +#endif /* __size_t__ */ +#undef __need_size_t +#endif /* _STDDEF_H or __need_size_t. */ + + +/* Wide character type. + Locale-writers should change this as necessary to + be big enough to hold unique values not between 0 and 127, + and not (wchar_t) -1, for each defined multibyte character. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_wchar_t) +#ifndef __wchar_t__ /* BeOS */ +#ifndef __WCHAR_T__ /* Cray Unicos/Mk */ +#ifndef _WCHAR_T +#ifndef _T_WCHAR_ +#ifndef _T_WCHAR +#ifndef __WCHAR_T +#ifndef _WCHAR_T_ +#ifndef _BSD_WCHAR_T_ +#ifndef _BSD_WCHAR_T_DEFINED_ /* Darwin */ +#ifndef _BSD_RUNE_T_DEFINED_ /* Darwin */ +#ifndef _WCHAR_T_DECLARED /* FreeBSD 5 */ +#ifndef __DEFINED_wchar_t /* musl libc */ +#ifndef _WCHAR_T_DEFINED_ +#ifndef _WCHAR_T_DEFINED +#ifndef _WCHAR_T_H +#ifndef ___int_wchar_t_h +#ifndef __INT_WCHAR_T_H +#ifndef _GCC_WCHAR_T +#define __wchar_t__ /* BeOS */ +#define __WCHAR_T__ /* Cray Unicos/Mk */ +#define _WCHAR_T +#define _T_WCHAR_ +#define _T_WCHAR +#define __WCHAR_T +#define _WCHAR_T_ +#define _BSD_WCHAR_T_ +#define _WCHAR_T_DEFINED_ +#define _WCHAR_T_DEFINED +#define _WCHAR_T_H +#define ___int_wchar_t_h +#define __INT_WCHAR_T_H +#define _GCC_WCHAR_T +#define _WCHAR_T_DECLARED +#define __DEFINED_wchar_t + +/* On BSD/386 1.1, at least, machine/ansi.h defines _BSD_WCHAR_T_ + instead of _WCHAR_T_, and _BSD_RUNE_T_ (which, unlike the other + symbols in the _FOO_T_ family, stays defined even after its + corresponding type is defined). If we define wchar_t, then we + must undef _WCHAR_T_; for BSD/386 1.1 (and perhaps others), if + we undef _WCHAR_T_, then we must also define rune_t, since + headers like runetype.h assume that if machine/ansi.h is included, + and _BSD_WCHAR_T_ is not defined, then rune_t is available. + machine/ansi.h says, "Note that _WCHAR_T_ and _RUNE_T_ must be of + the same type." */ +#ifdef _BSD_WCHAR_T_ +#undef _BSD_WCHAR_T_ +#ifdef _BSD_RUNE_T_ +#if !defined (_ANSI_SOURCE) && !defined (_POSIX_SOURCE) +typedef _BSD_RUNE_T_ rune_t; +#define _BSD_WCHAR_T_DEFINED_ +#define _BSD_RUNE_T_DEFINED_ /* Darwin */ +#if defined (__FreeBSD__) && (__FreeBSD__ < 5) +/* Why is this file so hard to maintain properly? In contrast to + the comment above regarding BSD/386 1.1, on FreeBSD for as long + as the symbol has existed, _BSD_RUNE_T_ must not stay defined or + redundant typedefs will occur when stdlib.h is included after this file. */ +#undef _BSD_RUNE_T_ +#endif +#endif +#endif +#endif +/* FreeBSD 5 can't be handled well using "traditional" logic above + since it no longer defines _BSD_RUNE_T_ yet still desires to export + rune_t in some cases... */ +#if defined (__FreeBSD__) && (__FreeBSD__ >= 5) +#if !defined (_ANSI_SOURCE) && !defined (_POSIX_SOURCE) +#if __BSD_VISIBLE +#ifndef _RUNE_T_DECLARED +typedef __rune_t rune_t; +#define _RUNE_T_DECLARED +#endif +#endif +#endif +#endif + +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif /* __DEFINED_wchar_t */ +#endif /* _WCHAR_T_DECLARED */ +#endif /* _BSD_RUNE_T_DEFINED_ */ +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif /* __WCHAR_T__ */ +#endif /* __wchar_t__ */ +#undef __need_wchar_t +#endif /* _STDDEF_H or __need_wchar_t. */ + +#if defined (__need_wint_t) +#ifndef _WINT_T +#define _WINT_T + +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ unsigned int +#endif +typedef __WINT_TYPE__ wint_t; +#endif +#undef __need_wint_t +#endif + +#if defined(__NetBSD__) +/* The references to _GCC_PTRDIFF_T_, _GCC_SIZE_T_, and _GCC_WCHAR_T_ + are probably typos and should be removed before 2.8 is released. */ +#ifdef _GCC_PTRDIFF_T_ +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#ifdef _GCC_SIZE_T_ +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#ifdef _GCC_WCHAR_T_ +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +/* The following ones are the real ones. */ +#ifdef _GCC_PTRDIFF_T +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#ifdef _GCC_SIZE_T +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#ifdef _GCC_WCHAR_T +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +#endif /* __NetBSD__ */ + +#endif /* __sys_stdtypes_h */ + +/* A null pointer constant. */ + +#if defined (_STDDEF_H) || defined (__need_NULL) +#undef NULL /* in case has defined it. */ +#ifdef __GNUG__ +#define NULL __null +#else /* G++ */ +#ifndef __cplusplus +#define NULL ((void *)0) +#else /* C++ */ +#define NULL 0 +#endif /* C++ */ +#endif /* G++ */ +#endif /* NULL not defined and or need NULL. */ +#undef __need_NULL + +#ifdef _STDDEF_H + +/* Offset of member MEMBER in a struct of type TYPE. */ +#undef offsetof /* in case a system header has defined it. */ +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) + +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ + || (defined(__cplusplus) && __cplusplus >= 201103L) +#ifndef _GCC_MAX_ALIGN_T +#define _GCC_MAX_ALIGN_T +/* Type whose alignment is supported in every context and is at least + as great as that of any standard type not using alignment + specifiers. */ +typedef struct { + long long __max_align_ll __attribute__((__aligned__(__alignof__(long long)))); + long double __max_align_ld __attribute__((__aligned__(__alignof__(long double)))); + /* _Float128 is defined as a basic type, so max_align_t must be + sufficiently aligned for it. This code must work in C++, so we + use __float128 here; that is only available on some + architectures, but only on i386 is extra alignment needed for + __float128. */ +#if defined(__i386__) && !defined(__clang__) + __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128)))); +#endif +} max_align_t; +#endif +#endif /* C11 or C++11. */ + +#if defined(__cplusplus) && __cplusplus >= 201103L +#ifndef _GXX_NULLPTR_T +#define _GXX_NULLPTR_T + typedef decltype(nullptr) nullptr_t; +#endif +#endif /* C++11. */ + +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) +#ifndef _GCC_NULLPTR_T +#define _GCC_NULLPTR_T + typedef __typeof__(nullptr) nullptr_t; +/* ??? This doesn't define __STDC_VERSION_STDDEF_H__ yet. */ +#endif +#endif /* C23. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define unreachable() (__builtin_unreachable ()) +#define __STDC_VERSION_STDDEF_H__ 202311L +#endif + +#endif /* _STDDEF_H was defined this time */ + +#endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__ + || __need_XXX was not defined before */ diff --git a/template/sysroot/include/stdfix.h b/template/sysroot/include/stdfix.h new file mode 100644 index 0000000..950c098 --- /dev/null +++ b/template/sysroot/include/stdfix.h @@ -0,0 +1,204 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* ISO/IEC JTC1 SC22 WG14 N1169 + * Date: 2006-04-04 + * ISO/IEC TR 18037 + * Programming languages - C - Extensions to support embedded processors + */ + +#ifndef _STDFIX_H +#define _STDFIX_H + +/* 7.18a.1 Introduction. */ + +#undef fract +#undef accum +#undef sat +#define fract _Fract +#define accum _Accum +#define sat _Sat + +/* 7.18a.3 Precision macros. */ + +#undef SFRACT_FBIT +#undef SFRACT_MIN +#undef SFRACT_MAX +#undef SFRACT_EPSILON +#define SFRACT_FBIT __SFRACT_FBIT__ +#define SFRACT_MIN __SFRACT_MIN__ +#define SFRACT_MAX __SFRACT_MAX__ +#define SFRACT_EPSILON __SFRACT_EPSILON__ + +#undef USFRACT_FBIT +#undef USFRACT_MIN +#undef USFRACT_MAX +#undef USFRACT_EPSILON +#define USFRACT_FBIT __USFRACT_FBIT__ +#define USFRACT_MIN __USFRACT_MIN__ /* GCC extension. */ +#define USFRACT_MAX __USFRACT_MAX__ +#define USFRACT_EPSILON __USFRACT_EPSILON__ + +#undef FRACT_FBIT +#undef FRACT_MIN +#undef FRACT_MAX +#undef FRACT_EPSILON +#define FRACT_FBIT __FRACT_FBIT__ +#define FRACT_MIN __FRACT_MIN__ +#define FRACT_MAX __FRACT_MAX__ +#define FRACT_EPSILON __FRACT_EPSILON__ + +#undef UFRACT_FBIT +#undef UFRACT_MIN +#undef UFRACT_MAX +#undef UFRACT_EPSILON +#define UFRACT_FBIT __UFRACT_FBIT__ +#define UFRACT_MIN __UFRACT_MIN__ /* GCC extension. */ +#define UFRACT_MAX __UFRACT_MAX__ +#define UFRACT_EPSILON __UFRACT_EPSILON__ + +#undef LFRACT_FBIT +#undef LFRACT_MIN +#undef LFRACT_MAX +#undef LFRACT_EPSILON +#define LFRACT_FBIT __LFRACT_FBIT__ +#define LFRACT_MIN __LFRACT_MIN__ +#define LFRACT_MAX __LFRACT_MAX__ +#define LFRACT_EPSILON __LFRACT_EPSILON__ + +#undef ULFRACT_FBIT +#undef ULFRACT_MIN +#undef ULFRACT_MAX +#undef ULFRACT_EPSILON +#define ULFRACT_FBIT __ULFRACT_FBIT__ +#define ULFRACT_MIN __ULFRACT_MIN__ /* GCC extension. */ +#define ULFRACT_MAX __ULFRACT_MAX__ +#define ULFRACT_EPSILON __ULFRACT_EPSILON__ + +#undef LLFRACT_FBIT +#undef LLFRACT_MIN +#undef LLFRACT_MAX +#undef LLFRACT_EPSILON +#define LLFRACT_FBIT __LLFRACT_FBIT__ /* GCC extension. */ +#define LLFRACT_MIN __LLFRACT_MIN__ /* GCC extension. */ +#define LLFRACT_MAX __LLFRACT_MAX__ /* GCC extension. */ +#define LLFRACT_EPSILON __LLFRACT_EPSILON__ /* GCC extension. */ + +#undef ULLFRACT_FBIT +#undef ULLFRACT_MIN +#undef ULLFRACT_MAX +#undef ULLFRACT_EPSILON +#define ULLFRACT_FBIT __ULLFRACT_FBIT__ /* GCC extension. */ +#define ULLFRACT_MIN __ULLFRACT_MIN__ /* GCC extension. */ +#define ULLFRACT_MAX __ULLFRACT_MAX__ /* GCC extension. */ +#define ULLFRACT_EPSILON __ULLFRACT_EPSILON__ /* GCC extension. */ + +#undef SACCUM_FBIT +#undef SACCUM_IBIT +#undef SACCUM_MIN +#undef SACCUM_MAX +#undef SACCUM_EPSILON +#define SACCUM_FBIT __SACCUM_FBIT__ +#define SACCUM_IBIT __SACCUM_IBIT__ +#define SACCUM_MIN __SACCUM_MIN__ +#define SACCUM_MAX __SACCUM_MAX__ +#define SACCUM_EPSILON __SACCUM_EPSILON__ + +#undef USACCUM_FBIT +#undef USACCUM_IBIT +#undef USACCUM_MIN +#undef USACCUM_MAX +#undef USACCUM_EPSILON +#define USACCUM_FBIT __USACCUM_FBIT__ +#define USACCUM_IBIT __USACCUM_IBIT__ +#define USACCUM_MIN __USACCUM_MIN__ /* GCC extension. */ +#define USACCUM_MAX __USACCUM_MAX__ +#define USACCUM_EPSILON __USACCUM_EPSILON__ + +#undef ACCUM_FBIT +#undef ACCUM_IBIT +#undef ACCUM_MIN +#undef ACCUM_MAX +#undef ACCUM_EPSILON +#define ACCUM_FBIT __ACCUM_FBIT__ +#define ACCUM_IBIT __ACCUM_IBIT__ +#define ACCUM_MIN __ACCUM_MIN__ +#define ACCUM_MAX __ACCUM_MAX__ +#define ACCUM_EPSILON __ACCUM_EPSILON__ + +#undef UACCUM_FBIT +#undef UACCUM_IBIT +#undef UACCUM_MIN +#undef UACCUM_MAX +#undef UACCUM_EPSILON +#define UACCUM_FBIT __UACCUM_FBIT__ +#define UACCUM_IBIT __UACCUM_IBIT__ +#define UACCUM_MIN __UACCUM_MIN__ /* GCC extension. */ +#define UACCUM_MAX __UACCUM_MAX__ +#define UACCUM_EPSILON __UACCUM_EPSILON__ + +#undef LACCUM_FBIT +#undef LACCUM_IBIT +#undef LACCUM_MIN +#undef LACCUM_MAX +#undef LACCUM_EPSILON +#define LACCUM_FBIT __LACCUM_FBIT__ +#define LACCUM_IBIT __LACCUM_IBIT__ +#define LACCUM_MIN __LACCUM_MIN__ +#define LACCUM_MAX __LACCUM_MAX__ +#define LACCUM_EPSILON __LACCUM_EPSILON__ + +#undef ULACCUM_FBIT +#undef ULACCUM_IBIT +#undef ULACCUM_MIN +#undef ULACCUM_MAX +#undef ULACCUM_EPSILON +#define ULACCUM_FBIT __ULACCUM_FBIT__ +#define ULACCUM_IBIT __ULACCUM_IBIT__ +#define ULACCUM_MIN __ULACCUM_MIN__ /* GCC extension. */ +#define ULACCUM_MAX __ULACCUM_MAX__ +#define ULACCUM_EPSILON __ULACCUM_EPSILON__ + +#undef LLACCUM_FBIT +#undef LLACCUM_IBIT +#undef LLACCUM_MIN +#undef LLACCUM_MAX +#undef LLACCUM_EPSILON +#define LLACCUM_FBIT __LLACCUM_FBIT__ /* GCC extension. */ +#define LLACCUM_IBIT __LLACCUM_IBIT__ /* GCC extension. */ +#define LLACCUM_MIN __LLACCUM_MIN__ /* GCC extension. */ +#define LLACCUM_MAX __LLACCUM_MAX__ /* GCC extension. */ +#define LLACCUM_EPSILON __LLACCUM_EPSILON__ /* GCC extension. */ + +#undef ULLACCUM_FBIT +#undef ULLACCUM_IBIT +#undef ULLACCUM_MIN +#undef ULLACCUM_MAX +#undef ULLACCUM_EPSILON +#define ULLACCUM_FBIT __ULLACCUM_FBIT__ /* GCC extension. */ +#define ULLACCUM_IBIT __ULLACCUM_IBIT__ /* GCC extension. */ +#define ULLACCUM_MIN __ULLACCUM_MIN__ /* GCC extension. */ +#define ULLACCUM_MAX __ULLACCUM_MAX__ /* GCC extension. */ +#define ULLACCUM_EPSILON __ULLACCUM_EPSILON__ /* GCC extension. */ + +#endif /* _STDFIX_H */ diff --git a/template/sysroot/include/stdint-gcc.h b/template/sysroot/include/stdint-gcc.h new file mode 100644 index 0000000..b3a1155 --- /dev/null +++ b/template/sysroot/include/stdint-gcc.h @@ -0,0 +1,402 @@ +/* Copyright (C) 2008-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.18 Integer types + */ + +#ifndef _GCC_STDINT_H +#define _GCC_STDINT_H + +/* 7.8.1.1 Exact-width integer types */ + +#ifdef __INT8_TYPE__ +typedef __INT8_TYPE__ int8_t; +#endif +#ifdef __INT16_TYPE__ +typedef __INT16_TYPE__ int16_t; +#endif +#ifdef __INT32_TYPE__ +typedef __INT32_TYPE__ int32_t; +#endif +#ifdef __INT64_TYPE__ +typedef __INT64_TYPE__ int64_t; +#endif +#ifdef __UINT8_TYPE__ +typedef __UINT8_TYPE__ uint8_t; +#endif +#ifdef __UINT16_TYPE__ +typedef __UINT16_TYPE__ uint16_t; +#endif +#ifdef __UINT32_TYPE__ +typedef __UINT32_TYPE__ uint32_t; +#endif +#ifdef __UINT64_TYPE__ +typedef __UINT64_TYPE__ uint64_t; +#endif + +/* 7.8.1.2 Minimum-width integer types */ + +typedef __INT_LEAST8_TYPE__ int_least8_t; +typedef __INT_LEAST16_TYPE__ int_least16_t; +typedef __INT_LEAST32_TYPE__ int_least32_t; +typedef __INT_LEAST64_TYPE__ int_least64_t; +typedef __UINT_LEAST8_TYPE__ uint_least8_t; +typedef __UINT_LEAST16_TYPE__ uint_least16_t; +typedef __UINT_LEAST32_TYPE__ uint_least32_t; +typedef __UINT_LEAST64_TYPE__ uint_least64_t; + +/* 7.8.1.3 Fastest minimum-width integer types */ + +typedef __INT_FAST8_TYPE__ int_fast8_t; +typedef __INT_FAST16_TYPE__ int_fast16_t; +typedef __INT_FAST32_TYPE__ int_fast32_t; +typedef __INT_FAST64_TYPE__ int_fast64_t; +typedef __UINT_FAST8_TYPE__ uint_fast8_t; +typedef __UINT_FAST16_TYPE__ uint_fast16_t; +typedef __UINT_FAST32_TYPE__ uint_fast32_t; +typedef __UINT_FAST64_TYPE__ uint_fast64_t; + +/* 7.8.1.4 Integer types capable of holding object pointers */ + +#ifdef __INTPTR_TYPE__ +typedef __INTPTR_TYPE__ intptr_t; +#endif +#ifdef __UINTPTR_TYPE__ +typedef __UINTPTR_TYPE__ uintptr_t; +#endif + +/* 7.8.1.5 Greatest-width integer types */ + +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +#if (!defined __cplusplus || __cplusplus >= 201103L \ + || defined __STDC_LIMIT_MACROS) + +/* 7.18.2 Limits of specified-width integer types */ + +#ifdef __INT8_MAX__ +# undef INT8_MAX +# define INT8_MAX __INT8_MAX__ +# undef INT8_MIN +# define INT8_MIN (-INT8_MAX - 1) +#endif +#ifdef __UINT8_MAX__ +# undef UINT8_MAX +# define UINT8_MAX __UINT8_MAX__ +#endif +#ifdef __INT16_MAX__ +# undef INT16_MAX +# define INT16_MAX __INT16_MAX__ +# undef INT16_MIN +# define INT16_MIN (-INT16_MAX - 1) +#endif +#ifdef __UINT16_MAX__ +# undef UINT16_MAX +# define UINT16_MAX __UINT16_MAX__ +#endif +#ifdef __INT32_MAX__ +# undef INT32_MAX +# define INT32_MAX __INT32_MAX__ +# undef INT32_MIN +# define INT32_MIN (-INT32_MAX - 1) +#endif +#ifdef __UINT32_MAX__ +# undef UINT32_MAX +# define UINT32_MAX __UINT32_MAX__ +#endif +#ifdef __INT64_MAX__ +# undef INT64_MAX +# define INT64_MAX __INT64_MAX__ +# undef INT64_MIN +# define INT64_MIN (-INT64_MAX - 1) +#endif +#ifdef __UINT64_MAX__ +# undef UINT64_MAX +# define UINT64_MAX __UINT64_MAX__ +#endif + +#undef INT_LEAST8_MAX +#define INT_LEAST8_MAX __INT_LEAST8_MAX__ +#undef INT_LEAST8_MIN +#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1) +#undef UINT_LEAST8_MAX +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#undef INT_LEAST16_MAX +#define INT_LEAST16_MAX __INT_LEAST16_MAX__ +#undef INT_LEAST16_MIN +#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1) +#undef UINT_LEAST16_MAX +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#undef INT_LEAST32_MAX +#define INT_LEAST32_MAX __INT_LEAST32_MAX__ +#undef INT_LEAST32_MIN +#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1) +#undef UINT_LEAST32_MAX +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#undef INT_LEAST64_MAX +#define INT_LEAST64_MAX __INT_LEAST64_MAX__ +#undef INT_LEAST64_MIN +#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1) +#undef UINT_LEAST64_MAX +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +#undef INT_FAST8_MAX +#define INT_FAST8_MAX __INT_FAST8_MAX__ +#undef INT_FAST8_MIN +#define INT_FAST8_MIN (-INT_FAST8_MAX - 1) +#undef UINT_FAST8_MAX +#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#undef INT_FAST16_MAX +#define INT_FAST16_MAX __INT_FAST16_MAX__ +#undef INT_FAST16_MIN +#define INT_FAST16_MIN (-INT_FAST16_MAX - 1) +#undef UINT_FAST16_MAX +#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#undef INT_FAST32_MAX +#define INT_FAST32_MAX __INT_FAST32_MAX__ +#undef INT_FAST32_MIN +#define INT_FAST32_MIN (-INT_FAST32_MAX - 1) +#undef UINT_FAST32_MAX +#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#undef INT_FAST64_MAX +#define INT_FAST64_MAX __INT_FAST64_MAX__ +#undef INT_FAST64_MIN +#define INT_FAST64_MIN (-INT_FAST64_MAX - 1) +#undef UINT_FAST64_MAX +#define UINT_FAST64_MAX __UINT_FAST64_MAX__ + +#ifdef __INTPTR_MAX__ +# undef INTPTR_MAX +# define INTPTR_MAX __INTPTR_MAX__ +# undef INTPTR_MIN +# define INTPTR_MIN (-INTPTR_MAX - 1) +#endif +#ifdef __UINTPTR_MAX__ +# undef UINTPTR_MAX +# define UINTPTR_MAX __UINTPTR_MAX__ +#endif + +#undef INTMAX_MAX +#define INTMAX_MAX __INTMAX_MAX__ +#undef INTMAX_MIN +#define INTMAX_MIN (-INTMAX_MAX - 1) +#undef UINTMAX_MAX +#define UINTMAX_MAX __UINTMAX_MAX__ + +/* 7.18.3 Limits of other integer types */ + +#undef PTRDIFF_MAX +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#undef PTRDIFF_MIN +#define PTRDIFF_MIN (-PTRDIFF_MAX - 1) + +#undef SIG_ATOMIC_MAX +#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ +#undef SIG_ATOMIC_MIN +#define SIG_ATOMIC_MIN (-SIG_ATOMIC_MAX - 1) + +#undef SIZE_MAX +#define SIZE_MAX __SIZE_MAX__ + +#undef WCHAR_MAX +#define WCHAR_MAX __WCHAR_MAX__ +#undef WCHAR_MIN +#define WCHAR_MIN (-WCHAR_MAX - 1) + +#undef WINT_MAX +#define WINT_MAX __WINT_MAX__ +#undef WINT_MIN +#define WINT_MIN (-WINT_MAX - 1) + +#endif /* (!defined __cplusplus || __cplusplus >= 201103L + || defined __STDC_LIMIT_MACROS) */ + +#if (!defined __cplusplus || __cplusplus >= 201103L \ + || defined __STDC_CONSTANT_MACROS) + +/* Clang and GCC have different mechanisms for INT32_C and friends. */ +#ifdef __clang__ +# ifndef __FSTD_HDRS_C_JOIN +# define __FSTD_HDRS_C_EXPAND_JOIN(x, suffix) x ## suffix +# define __FSTD_HDRS_C_JOIN(x, suffix) __FSTD_HDRS_C_EXPAND_JOIN(x, suffix) +# endif + +# undef INT8_C +# define INT8_C(x) __FSTD_HDRS_C_JOIN(x, __INT8_C_SUFFIX__) +# undef INT16_C +# define INT16_C(x) __FSTD_HDRS_C_JOIN(x, __INT16_C_SUFFIX__) +# undef INT32_C +# define INT32_C(x) __FSTD_HDRS_C_JOIN(x, __INT32_C_SUFFIX__) +# undef INT64_C +# define INT64_C(x) __FSTD_HDRS_C_JOIN(x, __INT64_C_SUFFIX__) + +# undef UINT8_C +# define UINT8_C(x) __FSTD_HDRS_C_JOIN(x, __UINT8_C_SUFFIX__) +# undef UINT16_C +# define UINT16_C(x) __FSTD_HDRS_C_JOIN(x, __UINT16_C_SUFFIX__) +# undef UINT32_C +# define UINT32_C(x) __FSTD_HDRS_C_JOIN(x, __UINT32_C_SUFFIX__) +# undef UINT64_C +# define UINT64_C(x) __FSTD_HDRS_C_JOIN(x, __UINT64_C_SUFFIX__) + +# undef INTMAX_C +# define INTMAX_C(x) __FSTD_HDRS_C_JOIN(x, __INTMAX_C_SUFFIX__) +# undef UINTMAX_C +# define UINTMAX_C(x) __FSTD_HDRS_C_JOIN(x, __UINTMAX_C_SUFFIX__) +#else +# undef INT8_C +# define INT8_C(x) __INT8_C(x) +# undef INT16_C +# define INT16_C(x) __INT16_C(x) +# undef INT32_C +# define INT32_C(x) __INT32_C(x) +# undef INT64_C +# define INT64_C(x) __INT64_C(x) + +# undef UINT8_C +# define UINT8_C(x) __UINT8_C(x) +# undef UINT16_C +# define UINT16_C(x) __UINT16_C(x) +# undef UINT32_C +# define UINT32_C(x) __UINT32_C(x) +# undef UINT64_C +# define UINT64_C(x) __UINT64_C(x) + +# undef INTMAX_C +# define INTMAX_C(x) __INTMAX_C(x) +# undef UINTMAX_C +# define UINTMAX_C(x) __UINTMAX_C(x) +#endif + +#endif /* (!defined __cplusplus || __cplusplus >= 201103L + || defined __STDC_CONSTANT_MACROS) */ + +#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \ + || (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L)) +/* TS 18661-1 / C23 widths of integer types. */ + +#ifdef __INT8_TYPE__ +# undef INT8_WIDTH +# define INT8_WIDTH 8 +#endif +#ifdef __UINT8_TYPE__ +# undef UINT8_WIDTH +# define UINT8_WIDTH 8 +#endif +#ifdef __INT16_TYPE__ +# undef INT16_WIDTH +# define INT16_WIDTH 16 +#endif +#ifdef __UINT16_TYPE__ +# undef UINT16_WIDTH +# define UINT16_WIDTH 16 +#endif +#ifdef __INT32_TYPE__ +# undef INT32_WIDTH +# define INT32_WIDTH 32 +#endif +#ifdef __UINT32_TYPE__ +# undef UINT32_WIDTH +# define UINT32_WIDTH 32 +#endif +#ifdef __INT64_TYPE__ +# undef INT64_WIDTH +# define INT64_WIDTH 64 +#endif +#ifdef __UINT64_TYPE__ +# undef UINT64_WIDTH +# define UINT64_WIDTH 64 +#endif + +#undef INT_LEAST8_WIDTH +#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__ +#undef UINT_LEAST8_WIDTH +#define UINT_LEAST8_WIDTH __INT_LEAST8_WIDTH__ +#undef INT_LEAST16_WIDTH +#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__ +#undef UINT_LEAST16_WIDTH +#define UINT_LEAST16_WIDTH __INT_LEAST16_WIDTH__ +#undef INT_LEAST32_WIDTH +#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__ +#undef UINT_LEAST32_WIDTH +#define UINT_LEAST32_WIDTH __INT_LEAST32_WIDTH__ +#undef INT_LEAST64_WIDTH +#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__ +#undef UINT_LEAST64_WIDTH +#define UINT_LEAST64_WIDTH __INT_LEAST64_WIDTH__ + +#undef INT_FAST8_WIDTH +#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__ +#undef UINT_FAST8_WIDTH +#define UINT_FAST8_WIDTH __INT_FAST8_WIDTH__ +#undef INT_FAST16_WIDTH +#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__ +#undef UINT_FAST16_WIDTH +#define UINT_FAST16_WIDTH __INT_FAST16_WIDTH__ +#undef INT_FAST32_WIDTH +#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__ +#undef UINT_FAST32_WIDTH +#define UINT_FAST32_WIDTH __INT_FAST32_WIDTH__ +#undef INT_FAST64_WIDTH +#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__ +#undef UINT_FAST64_WIDTH +#define UINT_FAST64_WIDTH __INT_FAST64_WIDTH__ + +#ifdef __INTPTR_TYPE__ +# undef INTPTR_WIDTH +# define INTPTR_WIDTH __INTPTR_WIDTH__ +#endif +#ifdef __UINTPTR_TYPE__ +# undef UINTPTR_WIDTH +# define UINTPTR_WIDTH __INTPTR_WIDTH__ +#endif + +#undef INTMAX_WIDTH +#define INTMAX_WIDTH __INTMAX_WIDTH__ +#undef UINTMAX_WIDTH +#define UINTMAX_WIDTH __INTMAX_WIDTH__ + +#undef PTRDIFF_WIDTH +#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__ + +#undef SIG_ATOMIC_WIDTH +#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__ + +#undef SIZE_WIDTH +#define SIZE_WIDTH __SIZE_WIDTH__ + +#undef WCHAR_WIDTH +#define WCHAR_WIDTH __WCHAR_WIDTH__ + +#undef WINT_WIDTH +#define WINT_WIDTH __WINT_WIDTH__ + +#endif + +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define __STDC_VERSION_STDINT_H__ 202311L +#endif + +#endif /* _GCC_STDINT_H */ diff --git a/template/sysroot/include/stdint.h b/template/sysroot/include/stdint.h new file mode 100644 index 0000000..83b6f70 --- /dev/null +++ b/template/sysroot/include/stdint.h @@ -0,0 +1,14 @@ +#ifndef _GCC_WRAP_STDINT_H +#if __STDC_HOSTED__ +# if defined __cplusplus && __cplusplus >= 201103L +# undef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# undef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +# endif +# include_next +#else +# include "stdint-gcc.h" +#endif +#define _GCC_WRAP_STDINT_H +#endif diff --git a/template/sysroot/include/stdnoreturn.h b/template/sysroot/include/stdnoreturn.h new file mode 100644 index 0000000..6261ff1 --- /dev/null +++ b/template/sysroot/include/stdnoreturn.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2011-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* ISO C1X: 7.23 _Noreturn . */ + +#ifndef _STDNORETURN_H +#define _STDNORETURN_H + +#ifndef __cplusplus + +#define noreturn _Noreturn + +#endif + +#endif /* stdnoreturn.h */ diff --git a/template/sysroot/include/string_view b/template/sysroot/include/string_view new file mode 100644 index 0000000..a7c5a12 --- /dev/null +++ b/template/sysroot/include/string_view @@ -0,0 +1,908 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/string_view + * This is a Standard C++ Library header. + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW +#define _GLIBCXX_STRING_VIEW 1 + +#pragma GCC system_header + +#define __glibcxx_want_constexpr_char_traits +#define __glibcxx_want_constexpr_string_view +#define __glibcxx_want_freestanding_string_view +#define __glibcxx_want_string_view +#define __glibcxx_want_starts_ends_with +#define __glibcxx_want_string_contains +#include + +#if __cplusplus >= 201703L + +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 202002L +# include +#endif + +#if _GLIBCXX_HOSTED +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Helper for basic_string and basic_string_view members. + constexpr size_t + __sv_check(size_t __size, size_t __pos, const char* __s) + { + if (__pos > __size) + __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " + "(which is %zu)"), __s, __pos, __size); + return __pos; + } + + // Helper for basic_string members. + // NB: __sv_limit doesn't check for a bad __pos value. + constexpr size_t + __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept + { + const bool __testoff = __off < __size - __pos; + return __testoff ? __off : __size - __pos; + } + + /** + * @class basic_string_view + * @brief A non-owning reference to a string. + * + * @ingroup strings + * @ingroup sequences + * + * @tparam _CharT Type of character + * @tparam _Traits Traits for character type, defaults to + * char_traits<_CharT>. + * + * A basic_string_view looks like this: + * + * @code + * _CharT* _M_str + * size_t _M_len + * @endcode + */ + template> + class basic_string_view + { + static_assert(!is_array_v<_CharT>); + static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>); + static_assert(is_same_v<_CharT, typename _Traits::char_type>); + + public: + + // types + using traits_type = _Traits; + using value_type = _CharT; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using const_iterator = const value_type*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + static constexpr size_type npos = size_type(-1); + + // [string.view.cons], construction and assignment + + constexpr + basic_string_view() noexcept + : _M_len{0}, _M_str{nullptr} + { } + + constexpr basic_string_view(const basic_string_view&) noexcept = default; + + [[__gnu__::__nonnull__]] + constexpr + basic_string_view(const _CharT* __str) noexcept + : _M_len{traits_type::length(__str)}, + _M_str{__str} + { } + + constexpr + basic_string_view(const _CharT* __str, size_type __len) noexcept + : _M_len{__len}, _M_str{__str} + { } + +#if __cplusplus >= 202002L && __cpp_lib_concepts + template _End> + requires same_as, _CharT> + && (!convertible_to<_End, size_type>) + constexpr + basic_string_view(_It __first, _End __last) + noexcept(noexcept(__last - __first)) + : _M_len(__last - __first), _M_str(std::to_address(__first)) + { } + +#if __cplusplus > 202002L + template> + requires (!is_same_v<_DRange, basic_string_view>) + && ranges::contiguous_range<_Range> + && ranges::sized_range<_Range> + && is_same_v, _CharT> + && (!is_convertible_v<_Range, const _CharT*>) + && (!requires (_DRange& __d) { + __d.operator ::std::basic_string_view<_CharT, _Traits>(); + }) + constexpr explicit + basic_string_view(_Range&& __r) + noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r))) + : _M_len(ranges::size(__r)), _M_str(ranges::data(__r)) + { } + + basic_string_view(nullptr_t) = delete; +#endif // C++23 +#endif // C++20 + + constexpr basic_string_view& + operator=(const basic_string_view&) noexcept = default; + + // [string.view.iterators], iterator support + + [[nodiscard]] + constexpr const_iterator + begin() const noexcept + { return this->_M_str; } + + [[nodiscard]] + constexpr const_iterator + end() const noexcept + { return this->_M_str + this->_M_len; } + + [[nodiscard]] + constexpr const_iterator + cbegin() const noexcept + { return this->_M_str; } + + [[nodiscard]] + constexpr const_iterator + cend() const noexcept + { return this->_M_str + this->_M_len; } + + [[nodiscard]] + constexpr const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + [[nodiscard]] + constexpr const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(this->begin()); } + + [[nodiscard]] + constexpr const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + [[nodiscard]] + constexpr const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(this->begin()); } + + // [string.view.capacity], capacity + + [[nodiscard]] + constexpr size_type + size() const noexcept + { return this->_M_len; } + + [[nodiscard]] + constexpr size_type + length() const noexcept + { return _M_len; } + + [[nodiscard]] + constexpr size_type + max_size() const noexcept + { + return (npos - sizeof(size_type) - sizeof(void*)) + / sizeof(value_type) / 4; + } + + [[nodiscard]] + constexpr bool + empty() const noexcept + { return this->_M_len == 0; } + + // [string.view.access], element access + + [[nodiscard]] + constexpr const_reference + operator[](size_type __pos) const noexcept + { + __glibcxx_assert(__pos < this->_M_len); + return *(this->_M_str + __pos); + } + + [[nodiscard]] + constexpr const_reference + at(size_type __pos) const + { + if (__pos >= _M_len) + __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " + "(which is %zu) >= this->size() " + "(which is %zu)"), __pos, this->size()); + return *(this->_M_str + __pos); + } + + [[nodiscard]] + constexpr const_reference + front() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *this->_M_str; + } + + [[nodiscard]] + constexpr const_reference + back() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *(this->_M_str + this->_M_len - 1); + } + + [[nodiscard]] + constexpr const_pointer + data() const noexcept + { return this->_M_str; } + + // [string.view.modifiers], modifiers: + + constexpr void + remove_prefix(size_type __n) noexcept + { + __glibcxx_assert(this->_M_len >= __n); + this->_M_str += __n; + this->_M_len -= __n; + } + + constexpr void + remove_suffix(size_type __n) noexcept + { + __glibcxx_assert(this->_M_len >= __n); + this->_M_len -= __n; + } + + constexpr void + swap(basic_string_view& __sv) noexcept + { + auto __tmp = *this; + *this = __sv; + __sv = __tmp; + } + + // [string.view.ops], string operations: + + _GLIBCXX20_CONSTEXPR + size_type + copy(_CharT* __str, size_type __n, size_type __pos = 0) const + { + __glibcxx_requires_string_len(__str, __n); + __pos = std::__sv_check(size(), __pos, "basic_string_view::copy"); + const size_type __rlen = std::min(__n, _M_len - __pos); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2777. basic_string_view::copy should use char_traits::copy + traits_type::copy(__str, data() + __pos, __rlen); + return __rlen; + } + + [[nodiscard]] + constexpr basic_string_view + substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) + { + __pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); + const size_type __rlen = std::min(__n, _M_len - __pos); + return basic_string_view{_M_str + __pos, __rlen}; + } + + [[nodiscard]] + constexpr int + compare(basic_string_view __str) const noexcept + { + const size_type __rlen = std::min(this->_M_len, __str._M_len); + int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); + if (__ret == 0) + __ret = _S_compare(this->_M_len, __str._M_len); + return __ret; + } + + [[nodiscard]] + constexpr int + compare(size_type __pos1, size_type __n1, basic_string_view __str) const + { return this->substr(__pos1, __n1).compare(__str); } + + [[nodiscard]] + constexpr int + compare(size_type __pos1, size_type __n1, + basic_string_view __str, size_type __pos2, size_type __n2) const + { + return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); + } + + [[nodiscard, __gnu__::__nonnull__]] + constexpr int + compare(const _CharT* __str) const noexcept + { return this->compare(basic_string_view{__str}); } + + [[nodiscard, __gnu__::__nonnull__]] + constexpr int + compare(size_type __pos1, size_type __n1, const _CharT* __str) const + { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } + + [[nodiscard]] + constexpr int + compare(size_type __pos1, size_type __n1, + const _CharT* __str, size_type __n2) const noexcept(false) + { + return this->substr(__pos1, __n1) + .compare(basic_string_view(__str, __n2)); + } + +#ifdef __cpp_lib_starts_ends_with // C++ >= 20 + [[nodiscard]] + constexpr bool + starts_with(basic_string_view __x) const noexcept + { return this->substr(0, __x.size()) == __x; } + + [[nodiscard]] + constexpr bool + starts_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->front(), __x); } + + [[nodiscard, __gnu__::__nonnull__]] + constexpr bool + starts_with(const _CharT* __x) const noexcept + { return this->starts_with(basic_string_view(__x)); } + + [[nodiscard]] + constexpr bool + ends_with(basic_string_view __x) const noexcept + { + const auto __len = this->size(); + const auto __xlen = __x.size(); + return __len >= __xlen + && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0; + } + + [[nodiscard]] + constexpr bool + ends_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->back(), __x); } + + [[nodiscard, __gnu__::__nonnull__]] + constexpr bool + ends_with(const _CharT* __x) const noexcept + { return this->ends_with(basic_string_view(__x)); } +#endif // __cpp_lib_starts_ends_with + +#if __cplusplus > 202002L +#if _GLIBCXX_HOSTED && !defined(__cpp_lib_string_contains) + // This FTM is not freestanding as it also implies matching + // support, and is omitted from the freestanding subset. +# error "libstdc++ bug: string_contains not defined when it should be" +#endif // HOSTED + [[nodiscard]] + constexpr bool + contains(basic_string_view __x) const noexcept + { return this->find(__x) != npos; } + + [[nodiscard]] + constexpr bool + contains(_CharT __x) const noexcept + { return this->find(__x) != npos; } + + [[nodiscard, __gnu__::__nonnull__]] + constexpr bool + contains(const _CharT* __x) const noexcept + { return this->find(__x) != npos; } +#endif // C++23 + + // [string.view.find], searching + + [[nodiscard]] + constexpr size_type + find(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + find(_CharT __c, size_type __pos = 0) const noexcept; + + [[nodiscard]] + constexpr size_type + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + find(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find(__str, __pos, traits_type::length(__str)); } + + [[nodiscard]] + constexpr size_type + rfind(basic_string_view __str, size_type __pos = npos) const noexcept + { return this->rfind(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + rfind(_CharT __c, size_type __pos = npos) const noexcept; + + [[nodiscard]] + constexpr size_type + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + rfind(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->rfind(__str, __pos, traits_type::length(__str)); } + + [[nodiscard]] + constexpr size_type + find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + find_first_of(_CharT __c, size_type __pos = 0) const noexcept + { return this->find(__c, __pos); } + + [[nodiscard]] + constexpr size_type + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str, __pos, traits_type::length(__str)); } + + [[nodiscard]] + constexpr size_type + find_last_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_of(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + find_last_of(_CharT __c, size_type __pos=npos) const noexcept + { return this->rfind(__c, __pos); } + + [[nodiscard]] + constexpr size_type + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->find_last_of(__str, __pos, traits_type::length(__str)); } + + [[nodiscard]] + constexpr size_type + find_first_not_of(basic_string_view __str, + size_type __pos = 0) const noexcept + { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; + + [[nodiscard]] + constexpr size_type + find_first_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept + { + return this->find_first_not_of(__str, __pos, + traits_type::length(__str)); + } + + [[nodiscard]] + constexpr size_type + find_last_not_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } + + [[nodiscard]] + constexpr size_type + find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; + + [[nodiscard]] + constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos = npos) const noexcept + { + return this->find_last_not_of(__str, __pos, + traits_type::length(__str)); + } + + private: + + static constexpr int + _S_compare(size_type __n1, size_type __n2) noexcept + { + using __limits = __gnu_cxx::__int_traits; + const difference_type __diff = __n1 - __n2; + if (__diff > __limits::__max) + return __limits::__max; + if (__diff < __limits::__min) + return __limits::__min; + return static_cast(__diff); + } + + size_t _M_len; + const _CharT* _M_str; + }; + +#if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides + template _End> + basic_string_view(_It, _End) -> basic_string_view>; + +#if __cplusplus > 202002L + template + basic_string_view(_Range&&) + -> basic_string_view>; +#endif +#endif + + // [string.view.comparison], non-member basic_string_view comparison function + + // Several of these functions use type_identity_t to create a non-deduced + // context, so that only one argument participates in template argument + // deduction and the other argument gets implicitly converted to the deduced + // type (see N3766). + +#if __cpp_lib_three_way_comparison + template + [[nodiscard]] + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + type_identity_t> __y) + noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + [[nodiscard]] + constexpr auto + operator<=>(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) + { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } +#else + template + [[nodiscard]] + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + [[nodiscard]] + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + [[nodiscard]] + constexpr bool + operator==(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + [[nodiscard]] + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + [[nodiscard]] + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return !(__x == __y); } + + template + [[nodiscard]] + constexpr bool + operator!=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + [[nodiscard]] + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + [[nodiscard]] + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) < 0; } + + template + [[nodiscard]] + constexpr bool + operator< (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + [[nodiscard]] + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + [[nodiscard]] + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) > 0; } + + template + [[nodiscard]] + constexpr bool + operator> (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + [[nodiscard]] + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + [[nodiscard]] + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) <= 0; } + + template + [[nodiscard]] + constexpr bool + operator<=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + [[nodiscard]] + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } + + template + [[nodiscard]] + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) >= 0; } + + template + [[nodiscard]] + constexpr bool + operator>=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } +#endif // three-way comparison + +#if _GLIBCXX_HOSTED + // [string.view.io], Inserters and extractors + template + inline basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + basic_string_view<_CharT,_Traits> __str) + { return __ostream_insert(__os, __str.data(), __str.size()); } +#endif // HOSTED + + // basic_string_view typedef names + + using string_view = basic_string_view; + using wstring_view = basic_string_view; +#ifdef _GLIBCXX_USE_CHAR8_T + using u8string_view = basic_string_view; +#endif + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + + // [string.view.hash], hash support: + + template + struct hash; + + template<> + struct hash + : public __hash_base + { + [[nodiscard]] + size_t + operator()(const string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + template<> + struct hash + : public __hash_base + { + [[nodiscard]] + size_t + operator()(const wstring_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(wchar_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct hash + : public __hash_base + { + [[nodiscard]] + size_t + operator()(const u8string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; +#endif + + template<> + struct hash + : public __hash_base + { + [[nodiscard]] + size_t + operator()(const u16string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char16_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + template<> + struct hash + : public __hash_base + { + [[nodiscard]] + size_t + operator()(const u32string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char32_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + inline namespace literals + { + inline namespace string_view_literals + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" + inline constexpr basic_string_view + operator""sv(const char* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + + inline constexpr basic_string_view + operator""sv(const wchar_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#ifdef _GLIBCXX_USE_CHAR8_T + inline constexpr basic_string_view + operator""sv(const char8_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } +#endif + + inline constexpr basic_string_view + operator""sv(const char16_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + + inline constexpr basic_string_view + operator""sv(const char32_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#pragma GCC diagnostic pop + } // namespace string_literals + } // namespace literals + +#if __cpp_lib_concepts + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> = true; + } +#endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#include + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW diff --git a/template/sysroot/include/syslimits.h b/template/sysroot/include/syslimits.h new file mode 100644 index 0000000..a362802 --- /dev/null +++ b/template/sysroot/include/syslimits.h @@ -0,0 +1,8 @@ +/* syslimits.h stands for the system's own limits.h file. + If we can use it ok unmodified, then we install this text. + If fixincludes fixes it, then the fixed version is installed + instead of this text. */ + +#define _GCC_NEXT_LIMITS_H /* tell gcc's limits.h to recurse */ +#include_next +#undef _GCC_NEXT_LIMITS_H diff --git a/template/sysroot/include/tbmintrin.h b/template/sysroot/include/tbmintrin.h new file mode 100644 index 0000000..a0d62b0 --- /dev/null +++ b/template/sysroot/include/tbmintrin.h @@ -0,0 +1,180 @@ +/* Copyright (C) 2010-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _TBMINTRIN_H_INCLUDED +#define _TBMINTRIN_H_INCLUDED + +#ifndef __TBM__ +#pragma GCC push_options +#pragma GCC target("tbm") +#define __DISABLE_TBM__ +#endif /* __TBM__ */ + +#ifdef __OPTIMIZE__ +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bextri_u32 (unsigned int __X, const unsigned int __I) +{ + return __builtin_ia32_bextri_u32 (__X, __I); +} +#else +#define __bextri_u32(X, I) \ + ((unsigned int)__builtin_ia32_bextri_u32 ((unsigned int)(X), \ + (unsigned int)(I))) +#endif /*__OPTIMIZE__ */ + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcfill_u32 (unsigned int __X) +{ + return __X & (__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blci_u32 (unsigned int __X) +{ + return __X | ~(__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcic_u32 (unsigned int __X) +{ + return ~__X & (__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcmsk_u32 (unsigned int __X) +{ + return __X ^ (__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcs_u32 (unsigned int __X) +{ + return __X | (__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsfill_u32 (unsigned int __X) +{ + return __X | (__X - 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsic_u32 (unsigned int __X) +{ + return ~__X | (__X - 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__t1mskc_u32 (unsigned int __X) +{ + return ~__X | (__X + 1); +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__tzmsk_u32 (unsigned int __X) +{ + return ~__X & (__X - 1); +} + + + +#ifdef __x86_64__ +#ifdef __OPTIMIZE__ +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__bextri_u64 (unsigned long long __X, const unsigned int __I) +{ + return __builtin_ia32_bextri_u64 (__X, __I); +} +#else +#define __bextri_u64(X, I) \ + ((unsigned long long)__builtin_ia32_bextri_u64 ((unsigned long long)(X), \ + (unsigned long long)(I))) +#endif /*__OPTIMIZE__ */ + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcfill_u64 (unsigned long long __X) +{ + return __X & (__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blci_u64 (unsigned long long __X) +{ + return __X | ~(__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcic_u64 (unsigned long long __X) +{ + return ~__X & (__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcmsk_u64 (unsigned long long __X) +{ + return __X ^ (__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blcs_u64 (unsigned long long __X) +{ + return __X | (__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsfill_u64 (unsigned long long __X) +{ + return __X | (__X - 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__blsic_u64 (unsigned long long __X) +{ + return ~__X | (__X - 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__t1mskc_u64 (unsigned long long __X) +{ + return ~__X | (__X + 1); +} + +extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__tzmsk_u64 (unsigned long long __X) +{ + return ~__X & (__X - 1); +} + + +#endif /* __x86_64__ */ + +#ifdef __DISABLE_TBM__ +#undef __DISABLE_TBM__ +#pragma GCC pop_options +#endif /* __DISABLE_TBM__ */ + +#endif /* _TBMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/tgmath.h b/template/sysroot/include/tgmath.h new file mode 100644 index 0000000..27ce89d --- /dev/null +++ b/template/sysroot/include/tgmath.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2004-2024 Free Software Foundation, Inc. + Contributed by Apple, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* + * ISO C Standard: 7.22 Type-generic math + */ + +#ifndef _TGMATH_H +#define _TGMATH_H + +#include + +#ifndef __cplusplus +#include + +/* Naming convention: generic macros are defining using + __TGMATH_CPLX*, __TGMATH_REAL*, and __TGMATH_CPLX_ONLY. _CPLX + means the generic argument(s) may be real or complex, _REAL means + real only, _CPLX means complex only. If there is no suffix, we are + defining a function of one argument. If the suffix is _n + it is a function of n arguments. We only define these macros for + values of n that are needed. */ + +#define __TGMATH_CPLX(z,R,C) \ + __builtin_tgmath (R##f, R, R##l, C##f, C, C##l, (z)) + +#define __TGMATH_CPLX_2(z1,z2,R,C) \ + __builtin_tgmath (R##f, R, R##l, C##f, C, C##l, (z1), (z2)) + +#define __TGMATH_REAL(x,R) \ + __builtin_tgmath (R##f, R, R##l, (x)) +#define __TGMATH_REAL_2(x,y,R) \ + __builtin_tgmath (R##f, R, R##l, (x), (y)) +#define __TGMATH_REAL_3(x,y,z,R) \ + __builtin_tgmath (R##f, R, R##l, (x), (y), (z)) +#define __TGMATH_CPLX_ONLY(z,C) \ + __builtin_tgmath (C##f, C, C##l, (z)) + +/* Functions defined in both and (7.22p4) */ +#define acos(z) __TGMATH_CPLX(z, acos, cacos) +#define asin(z) __TGMATH_CPLX(z, asin, casin) +#define atan(z) __TGMATH_CPLX(z, atan, catan) +#define acosh(z) __TGMATH_CPLX(z, acosh, cacosh) +#define asinh(z) __TGMATH_CPLX(z, asinh, casinh) +#define atanh(z) __TGMATH_CPLX(z, atanh, catanh) +#define cos(z) __TGMATH_CPLX(z, cos, ccos) +#define sin(z) __TGMATH_CPLX(z, sin, csin) +#define tan(z) __TGMATH_CPLX(z, tan, ctan) +#define cosh(z) __TGMATH_CPLX(z, cosh, ccosh) +#define sinh(z) __TGMATH_CPLX(z, sinh, csinh) +#define tanh(z) __TGMATH_CPLX(z, tanh, ctanh) +#define exp(z) __TGMATH_CPLX(z, exp, cexp) +#define log(z) __TGMATH_CPLX(z, log, clog) +#define pow(z1,z2) __TGMATH_CPLX_2(z1, z2, pow, cpow) +#define sqrt(z) __TGMATH_CPLX(z, sqrt, csqrt) +#define fabs(z) __TGMATH_CPLX(z, fabs, cabs) + +/* Functions defined in only (7.22p5) */ +#define atan2(x,y) __TGMATH_REAL_2(x, y, atan2) +#define cbrt(x) __TGMATH_REAL(x, cbrt) +#define ceil(x) __TGMATH_REAL(x, ceil) +#define copysign(x,y) __TGMATH_REAL_2(x, y, copysign) +#define erf(x) __TGMATH_REAL(x, erf) +#define erfc(x) __TGMATH_REAL(x, erfc) +#define exp2(x) __TGMATH_REAL(x, exp2) +#define expm1(x) __TGMATH_REAL(x, expm1) +#define fdim(x,y) __TGMATH_REAL_2(x, y, fdim) +#define floor(x) __TGMATH_REAL(x, floor) +#define fma(x,y,z) __TGMATH_REAL_3(x, y, z, fma) +#define fmax(x,y) __TGMATH_REAL_2(x, y, fmax) +#define fmin(x,y) __TGMATH_REAL_2(x, y, fmin) +#define fmod(x,y) __TGMATH_REAL_2(x, y, fmod) +#define frexp(x,y) __TGMATH_REAL_2(x, y, frexp) +#define hypot(x,y) __TGMATH_REAL_2(x, y, hypot) +#define ilogb(x) __TGMATH_REAL(x, ilogb) +#define ldexp(x,y) __TGMATH_REAL_2(x, y, ldexp) +#define lgamma(x) __TGMATH_REAL(x, lgamma) +#define llrint(x) __TGMATH_REAL(x, llrint) +#define llround(x) __TGMATH_REAL(x, llround) +#define log10(x) __TGMATH_REAL(x, log10) +#define log1p(x) __TGMATH_REAL(x, log1p) +#define log2(x) __TGMATH_REAL(x, log2) +#define logb(x) __TGMATH_REAL(x, logb) +#define lrint(x) __TGMATH_REAL(x, lrint) +#define lround(x) __TGMATH_REAL(x, lround) +#define nearbyint(x) __TGMATH_REAL(x, nearbyint) +#define nextafter(x,y) __TGMATH_REAL_2(x, y, nextafter) +#define nexttoward(x,y) __TGMATH_REAL_2(x, y, nexttoward) +#define remainder(x,y) __TGMATH_REAL_2(x, y, remainder) +#define remquo(x,y,z) __TGMATH_REAL_3(x, y, z, remquo) +#define rint(x) __TGMATH_REAL(x, rint) +#define round(x) __TGMATH_REAL(x, round) +#define scalbn(x,y) __TGMATH_REAL_2(x, y, scalbn) +#define scalbln(x,y) __TGMATH_REAL_2(x, y, scalbln) +#define tgamma(x) __TGMATH_REAL(x, tgamma) +#define trunc(x) __TGMATH_REAL(x, trunc) + +/* Functions defined in only (7.22p6) */ +#define carg(z) __TGMATH_CPLX_ONLY(z, carg) +#define cimag(z) __TGMATH_CPLX_ONLY(z, cimag) +#define conj(z) __TGMATH_CPLX_ONLY(z, conj) +#define cproj(z) __TGMATH_CPLX_ONLY(z, cproj) +#define creal(z) __TGMATH_CPLX_ONLY(z, creal) + +#endif /* __cplusplus */ +#endif /* _TGMATH_H */ diff --git a/template/sysroot/include/tls/tls.hpp b/template/sysroot/include/tls/tls.hpp new file mode 100644 index 0000000..9555a49 --- /dev/null +++ b/template/sysroot/include/tls/tls.hpp @@ -0,0 +1,45 @@ +/* + * tls.hpp + * Shared TLS helper library for MontaukOS + * Trust anchor loading, BearSSL time, TLS I/O, HTTPS fetch + * Copyright (c) 2026 Daniel Hammer + */ + +#pragma once + +extern "C" { +#include +} + +#include +#include + +namespace tls { + +struct TrustAnchors { + br_x509_trust_anchor* anchors; + size_t count; + size_t capacity; +}; + +TrustAnchors load_trust_anchors(); +void get_bearssl_time(uint32_t* days, uint32_t* seconds); +int tls_send_all(int fd, const unsigned char* data, size_t len); +int tls_recv_some(int fd, unsigned char* buf, size_t maxlen); + +// Optional abort callback (for Ctrl+Q in terminal apps). nullptr = no abort. +using AbortCheckFn = bool (*)(); + +int tls_exchange(int fd, br_ssl_engine_context* eng, + const char* request, int reqLen, + char* respBuf, int respMax, + AbortCheckFn abort_check = nullptr); + +// High-level: socket -> TLS setup -> exchange -> cleanup, all in one call. +int https_fetch(const char* host, uint32_t ip, uint16_t port, + const char* request, int reqLen, + const TrustAnchors& tas, + char* respBuf, int respMax, + AbortCheckFn abort_check = nullptr); + +} // namespace tls diff --git a/template/sysroot/include/tmmintrin.h b/template/sysroot/include/tmmintrin.h new file mode 100644 index 0000000..f1b3303 --- /dev/null +++ b/template/sysroot/include/tmmintrin.h @@ -0,0 +1,249 @@ +/* Copyright (C) 2006-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 9.1. */ + +#ifndef _TMMINTRIN_H_INCLUDED +#define _TMMINTRIN_H_INCLUDED + +/* We need definitions from the SSE3, SSE2 and SSE header files*/ +#include + +#ifndef __SSSE3__ +#pragma GCC push_options +#pragma GCC target("ssse3") +#define __DISABLE_SSSE3__ +#endif /* __SSSE3__ */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phaddw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phaddd128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadds_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phaddsw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phaddw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadd_pi32 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phaddd ((__v2si)__X, (__v2si)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hadds_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phaddsw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phsubw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phsubd128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsubs_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_phsubsw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phsubw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsub_pi32 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phsubd ((__v2si)__X, (__v2si)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsubs_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_phsubsw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddubs_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmaddubsw128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddubs_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_pmaddubsw ((__v8qi)__X, (__v8qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhrs_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pmulhrsw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhrs_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_pmulhrsw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_pshufb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_pi8 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_pshufb ((__v8qi)__X, (__v8qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_epi8 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psignb128 ((__v16qi)__X, (__v16qi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_epi16 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psignw128 ((__v8hi)__X, (__v8hi)__Y); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_epi32 (__m128i __X, __m128i __Y) +{ + return (__m128i) __builtin_ia32_psignd128 ((__v4si)__X, (__v4si)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_pi8 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_psignb ((__v8qi)__X, (__v8qi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_pi16 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_psignw ((__v4hi)__X, (__v4hi)__Y); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sign_pi32 (__m64 __X, __m64 __Y) +{ + return (__m64) __builtin_ia32_psignd ((__v2si)__X, (__v2si)__Y); +} + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_alignr_epi8(__m128i __X, __m128i __Y, const int __N) +{ + return (__m128i) __builtin_ia32_palignr128 ((__v2di)__X, + (__v2di)__Y, __N * 8); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_alignr_pi8(__m64 __X, __m64 __Y, const int __N) +{ + return (__m64) __builtin_ia32_palignr ((__v1di)__X, + (__v1di)__Y, __N * 8); +} +#else +#define _mm_alignr_epi8(X, Y, N) \ + ((__m128i) __builtin_ia32_palignr128 ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), \ + (int)(N) * 8)) +#define _mm_alignr_pi8(X, Y, N) \ + ((__m64) __builtin_ia32_palignr ((__v1di)(__m64)(X), \ + (__v1di)(__m64)(Y), \ + (int)(N) * 8)) +#endif + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_epi8 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pabsb128 ((__v16qi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_epi16 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pabsw128 ((__v8hi)__X); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_epi32 (__m128i __X) +{ + return (__m128i) __builtin_ia32_pabsd128 ((__v4si)__X); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_pi8 (__m64 __X) +{ + return (__m64) __builtin_ia32_pabsb ((__v8qi)__X); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_pi16 (__m64 __X) +{ + return (__m64) __builtin_ia32_pabsw ((__v4hi)__X); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_abs_pi32 (__m64 __X) +{ + return (__m64) __builtin_ia32_pabsd ((__v2si)__X); +} + +#ifdef __DISABLE_SSSE3__ +#undef __DISABLE_SSSE3__ +#pragma GCC pop_options +#endif /* __DISABLE_SSSE3__ */ + +#endif /* _TMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/tsxldtrkintrin.h b/template/sysroot/include/tsxldtrkintrin.h new file mode 100644 index 0000000..525723f --- /dev/null +++ b/template/sysroot/include/tsxldtrkintrin.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _TSXLDTRKINTRIN_H_INCLUDED +#define _TSXLDTRKINTRIN_H_INCLUDED + +#if !defined(__TSXLDTRK__) +#pragma GCC push_options +#pragma GCC target("tsxldtrk") +#define __DISABLE_TSXLDTRK__ +#endif /* __TSXLDTRK__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsusldtrk (void) +{ + __builtin_ia32_xsusldtrk (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xresldtrk (void) +{ + __builtin_ia32_xresldtrk (); +} + +#ifdef __DISABLE_TSXLDTRK__ +#undef __DISABLE_TSXLDTRK__ +#pragma GCC pop_options +#endif /* __DISABLE_TSXLDTRK__ */ + +#endif /* _TSXLDTRKINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/tuple b/template/sysroot/include/tuple new file mode 100644 index 0000000..3065058 --- /dev/null +++ b/template/sysroot/include/tuple @@ -0,0 +1,3035 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/tuple + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TUPLE +#define _GLIBCXX_TUPLE 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include // for std::pair +#include // for std::allocator_arg_t +#include // for std::tuple_size etc. +#include // for std::__invoke +#if __cplusplus > 201703L +# include +# include // for std::ranges::subrange +#endif + +#define __glibcxx_want_constexpr_tuple +#define __glibcxx_want_tuple_element_t +#define __glibcxx_want_tuples_by_type +#define __glibcxx_want_apply +#define __glibcxx_want_make_from_tuple +#define __glibcxx_want_ranges_zip +#define __glibcxx_want_tuple_like +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + template + class tuple; + + template + struct __is_empty_non_tuple : is_empty<_Tp> { }; + + // Using EBO for elements that are tuples causes ambiguous base errors. + template + struct __is_empty_non_tuple> : false_type { }; + + // Use the Empty Base-class Optimization for empty, non-final types. + template + using __empty_not_final + = __conditional_t<__is_final(_Tp), false_type, + __is_empty_non_tuple<_Tp>>; + + template::value> + struct _Head_base; + +#if __has_cpp_attribute(__no_unique_address__) + template + struct _Head_base<_Idx, _Head, true> + { + constexpr _Head_base() + : _M_head_impl() { } + + constexpr _Head_base(const _Head& __h) + : _M_head_impl(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _M_head_impl(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _M_head_impl() { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } + + [[__no_unique_address__]] _Head _M_head_impl; + }; +#else + template + struct _Head_base<_Idx, _Head, true> + : public _Head + { + constexpr _Head_base() + : _Head() { } + + constexpr _Head_base(const _Head& __h) + : _Head(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _Head(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _Head() { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _Head(allocator_arg, *__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _Head(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead)) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b; } + }; +#endif + + template + struct _Head_base<_Idx, _Head, false> + { + constexpr _Head_base() + : _M_head_impl() { } + + constexpr _Head_base(const _Head& __h) + : _M_head_impl(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _M_head_impl(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _M_head_impl() { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } + + _Head _M_head_impl; + }; + +#if __cpp_lib_tuple_like // >= C++23 + struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; }; + + // These forward declarations are used by the operator<=> overload for + // tuple-like types. + template + constexpr _Cat + __tuple_cmp(const _Tp&, const _Up&, index_sequence<>); + + template + constexpr _Cat + __tuple_cmp(const _Tp& __t, const _Up& __u, + index_sequence<_Idx0, _Idxs...>); +#endif // C++23 + + /** + * Contains the actual implementation of the @c tuple template, stored + * as a recursive inheritance hierarchy from the first element (most + * derived class) to the last (least derived class). The @c Idx + * parameter gives the 0-based index of the element stored at this + * point in the hierarchy; we use it to implement a constant-time + * get() operation. + */ + template + struct _Tuple_impl; + + /** + * Recursive tuple implementation. Here we store the @c Head element + * and derive from a @c Tuple_impl containing the remaining elements + * (which contains the @c Tail). + */ + template + struct _Tuple_impl<_Idx, _Head, _Tail...> + : public _Tuple_impl<_Idx + 1, _Tail...>, + private _Head_base<_Idx, _Head> + { + template friend struct _Tuple_impl; + + typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr _Inherited& + _M_tail(_Tuple_impl& __t) noexcept { return __t; } + + static constexpr const _Inherited& + _M_tail(const _Tuple_impl& __t) noexcept { return __t; } + + constexpr _Tuple_impl() + : _Inherited(), _Base() { } + + explicit constexpr + _Tuple_impl(const _Head& __head, const _Tail&... __tail) + : _Inherited(__tail...), _Base(__head) + { } + + template> + explicit constexpr + _Tuple_impl(_UHead&& __head, _UTail&&... __tail) + : _Inherited(std::forward<_UTail>(__tail)...), + _Base(std::forward<_UHead>(__head)) + { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + + _Tuple_impl(_Tuple_impl&&) = default; + + template + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr + _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>) + : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...) + { } +#endif // C++23 + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a), + _Base(__tag, __use_alloc<_Head>(__a)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head, const _Tail&... __tail) + : _Inherited(__tag, __a, __tail...), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) + { } + + template> + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head, _UTail&&... __tail) + : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Inherited(__tag, __a, _M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + : _Inherited(__tag, __a, std::move(_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead, _UTails...>& __in) + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>& __in) + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a), + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a), + std::forward + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr + _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a, + _UTuple&& __u, index_sequence<_Is...>) + : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...) + { } +#endif // C++23 + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this)._M_assign( + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + { + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this)._M_assign( + std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); + } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr void + _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const + { + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this)._M_assign( + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); + } + + template + constexpr void + _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const + { + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this)._M_assign( + std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); + } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr void + _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) + { + _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); + _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u)); + } + + template + constexpr void + _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const + { + _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); + _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u)); + } +#endif // C++23 + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); + } + +#if __cpp_lib_ranges_zip // >= C++23 + constexpr void + _M_swap(const _Tuple_impl& __in) const + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); + } +#endif // C++23 + }; + + // Basis case of inheritance recursion. + template + struct _Tuple_impl<_Idx, _Head> + : private _Head_base<_Idx, _Head> + { + template friend struct _Tuple_impl; + + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + constexpr + _Tuple_impl() + : _Base() { } + + explicit constexpr + _Tuple_impl(const _Head& __head) + : _Base(__head) + { } + + template + explicit constexpr + _Tuple_impl(_UHead&& __head) + : _Base(std::forward<_UHead>(__head)) + { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + +#if _GLIBCXX_INLINE_VERSION + _Tuple_impl(_Tuple_impl&&) = default; +#else + constexpr + _Tuple_impl(_Tuple_impl&& __in) + noexcept(is_nothrow_move_constructible<_Head>::value) + : _Base(static_cast<_Base&&>(__in)) + { } +#endif + + template + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) + : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in) + : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(std::forward(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr + _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>) + : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u))) + { } +#endif // C++23 + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Base(__tag, __use_alloc<_Head>(__a)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + const _Head& __head) + : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + _UHead&& __head) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + const _Tuple_impl& __in) + : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + _Tuple_impl&& __in) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead>& __in) + : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a), + _Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template + constexpr + _Tuple_impl(allocator_arg_t, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a), + std::forward(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr + _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a, + _UTuple&& __u, index_sequence<0>) + : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u))) + { } +#endif // C++23 + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) + { + _M_head(*this) + = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); + } + +#if __cpp_lib_ranges_zip // >= C++23 + template + constexpr void + _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const + { + _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); + } + + template + constexpr void + _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const + { + _M_head(*this) + = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); + } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + constexpr void + _M_assign(__tuple_like_tag_t, _UTuple&& __u) + { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); } + + template + constexpr void + _M_assign(__tuple_like_tag_t, _UTuple&& __u) const + { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); } +#endif // C++23 + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + } + +#if __cpp_lib_ranges_zip // >= C++23 + constexpr void + _M_swap(const _Tuple_impl& __in) const + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + } +#endif // C++23 + }; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + template + struct _TupleConstraints + { + template + using __constructible = __and_...>; + + template + using __convertible = __and_...>; + + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // and every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_implicitly_constructible() + { + return __and_<__constructible<_UTypes...>, + __convertible<_UTypes...> + >::value; + } + + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // but not every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_explicitly_constructible() + { + return __and_<__constructible<_UTypes...>, + __not_<__convertible<_UTypes...>> + >::value; + } + + static constexpr bool __is_implicitly_default_constructible() + { + return __and_... + >::value; + } + + static constexpr bool __is_explicitly_default_constructible() + { + return __and_..., + __not_<__and_< + std::__is_implicitly_default_constructible<_Types>...> + >>::value; + } + }; + + // Partial specialization used when a required precondition isn't met, + // e.g. when sizeof...(_Types) != sizeof...(_UTypes). + template + struct _TupleConstraints + { + template + static constexpr bool __is_implicitly_constructible() + { return false; } + + template + static constexpr bool __is_explicitly_constructible() + { return false; } + }; + + /// Primary class template, tuple + template + class tuple : public _Tuple_impl<0, _Elements...> + { + using _Inherited = _Tuple_impl<0, _Elements...>; + +#if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20 + template + static consteval bool + __constructible() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } + + template + static consteval bool + __nothrow_constructible() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } + + template + static consteval bool + __convertible() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3121. tuple constructor constraints for UTypes&&... overloads + template + static consteval bool + __disambiguating_constraint() + { + if constexpr (sizeof...(_Elements) != sizeof...(_UTypes)) + return false; + else if constexpr (sizeof...(_Elements) == 1) + { + using _U0 = typename _Nth_type<0, _UTypes...>::type; + return !is_same_v, tuple>; + } + else if constexpr (sizeof...(_Elements) < 4) + { + using _U0 = typename _Nth_type<0, _UTypes...>::type; + if constexpr (!is_same_v, allocator_arg_t>) + return true; + else + { + using _T0 = typename _Nth_type<0, _Elements...>::type; + return is_same_v, allocator_arg_t>; + } + } + return true; + } + + // Return true iff sizeof...(Types) == 1 && tuple_size_v == 1 + // and the single element in Types can be initialized from TUPLE, + // or is the same type as tuple_element_t<0, TUPLE>. + template + static consteval bool + __use_other_ctor() + { + if constexpr (sizeof...(_Elements) != 1) + return false; + else if constexpr (is_same_v, tuple>) + return true; // Should use a copy/move constructor instead. + else + { + using _Tp = typename _Nth_type<0, _Elements...>::type; + if constexpr (is_convertible_v<_Tuple, _Tp>) + return true; + else if constexpr (is_constructible_v<_Tp, _Tuple>) + return true; + } + return false; + } + + template + static consteval bool + __dangles() + { +#if __has_builtin(__reference_constructs_from_temporary) + return (__reference_constructs_from_temporary(_Elements, _Up&&) + || ...); +#else + return false; +#endif + } + +#if __cpp_lib_tuple_like // >= C++23 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4045. tuple can create dangling references from tuple-like + template + static consteval bool + __dangles_from_tuple_like() + { + return [](index_sequence<_Is...>) { + return __dangles(std::declval<_UTuple>()))...>(); + }(index_sequence_for<_Elements...>{}); + } + + template + static consteval bool + __constructible_from_tuple_like() + { + return [](index_sequence<_Is...>) { + return __constructible(std::declval<_UTuple>()))...>(); + }(index_sequence_for<_Elements...>{}); + } + + template + static consteval bool + __convertible_from_tuple_like() + { + return [](index_sequence<_Is...>) { + return __convertible(std::declval<_UTuple>()))...>(); + }(index_sequence_for<_Elements...>{}); + } +#endif // C++23 + + public: + constexpr + explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...)) + tuple() + noexcept((is_nothrow_default_constructible_v<_Elements> && ...)) + requires (is_default_constructible_v<_Elements> && ...) + : _Inherited() + { } + + constexpr explicit(!__convertible()) + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + requires (__constructible()) + : _Inherited(__elements...) + { } + + template + requires (__disambiguating_constraint<_UTypes...>()) + && (__constructible<_UTypes...>()) + && (!__dangles<_UTypes...>()) + constexpr explicit(!__convertible<_UTypes...>()) + tuple(_UTypes&&... __u) + noexcept(__nothrow_constructible<_UTypes...>()) + : _Inherited(std::forward<_UTypes>(__u)...) + { } + + template + requires (__disambiguating_constraint<_UTypes...>()) + && (__constructible<_UTypes...>()) + && (__dangles<_UTypes...>()) + tuple(_UTypes&&...) = delete; + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template + requires (__constructible()) + && (!__use_other_ctor&>()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(const tuple<_UTypes...>& __u) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__u)) + { } + + template + requires (__constructible()) + && (!__use_other_ctor&>()) + && (__dangles()) + tuple(const tuple<_UTypes...>&) = delete; + + template + requires (__constructible<_UTypes...>()) + && (!__use_other_ctor>()) + && (!__dangles<_UTypes...>()) + constexpr explicit(!__convertible<_UTypes...>()) + tuple(tuple<_UTypes...>&& __u) + noexcept(__nothrow_constructible<_UTypes...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u)) + { } + + template + requires (__constructible<_UTypes...>()) + && (!__use_other_ctor>()) + && (__dangles<_UTypes...>()) + tuple(tuple<_UTypes...>&&) = delete; + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (__constructible<_UTypes&...>()) + && (!__use_other_ctor&>()) + && (!__dangles<_UTypes&...>()) + constexpr explicit(!__convertible<_UTypes&...>()) + tuple(tuple<_UTypes...>& __u) + noexcept(__nothrow_constructible<_UTypes&...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u)) + { } + + template + requires (__constructible<_UTypes&...>()) + && (!__use_other_ctor&>()) + && (__dangles<_UTypes&...>()) + tuple(tuple<_UTypes...>&) = delete; + + template + requires (__constructible()) + && (!__use_other_ctor>()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(const tuple<_UTypes...>&& __u) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&&>(__u)) + { } + + template + requires (__constructible()) + && (!__use_other_ctor>()) + && (__dangles()) + tuple(const tuple<_UTypes...>&&) = delete; +#endif // C++23 + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(const pair<_U1, _U2>& __u) + noexcept(__nothrow_constructible()) + : _Inherited(__u.first, __u.second) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (__dangles()) + tuple(const pair<_U1, _U2>&) = delete; + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1, _U2>()) + && (!__dangles<_U1, _U2>()) + constexpr explicit(!__convertible<_U1, _U2>()) + tuple(pair<_U1, _U2>&& __u) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__u.first), + std::forward<_U2>(__u.second)) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1, _U2>()) + && (__dangles<_U1, _U2>()) + tuple(pair<_U1, _U2>&&) = delete; + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1&, _U2&>()) + && (!__dangles<_U1&, _U2&>()) + constexpr explicit(!__convertible<_U1&, _U2&>()) + tuple(pair<_U1, _U2>& __u) + noexcept(__nothrow_constructible<_U1&, _U2&>()) + : _Inherited(__u.first, __u.second) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1&, _U2&>()) + && (__dangles<_U1&, _U2&>()) + tuple(pair<_U1, _U2>&) = delete; + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(const pair<_U1, _U2>&& __u) + noexcept(__nothrow_constructible()) + : _Inherited(std::forward(__u.first), + std::forward(__u.second)) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (__dangles()) + tuple(const pair<_U1, _U2>&&) = delete; +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template<__eligible_tuple_like _UTuple> + requires (__constructible_from_tuple_like<_UTuple>()) + && (!__use_other_ctor<_UTuple>()) + && (!__dangles_from_tuple_like<_UTuple>()) + constexpr explicit(!__convertible_from_tuple_like<_UTuple>()) + tuple(_UTuple&& __u) + : _Inherited(__tuple_like_tag_t{}, + std::forward<_UTuple>(__u), + index_sequence_for<_Elements...>{}) + { } + + template<__eligible_tuple_like _UTuple> + requires (__constructible_from_tuple_like<_UTuple>()) + && (!__use_other_ctor<_UTuple>()) + && (__dangles_from_tuple_like<_UTuple>()) + tuple(_UTuple&&) = delete; +#endif // C++23 + + // Allocator-extended constructors. + + template + constexpr + explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...)) + tuple(allocator_arg_t __tag, const _Alloc& __a) + requires (is_default_constructible_v<_Elements> && ...) + : _Inherited(__tag, __a) + { } + + template + constexpr explicit(!__convertible()) + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + requires (__constructible()) + : _Inherited(__tag, __a, __elements...) + { } + + template + requires (__disambiguating_constraint<_UTypes...>()) + && (__constructible<_UTypes...>()) + && (!__dangles<_UTypes...>()) + constexpr explicit(!__convertible<_UTypes...>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u) + : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...) + { } + + template + requires (__disambiguating_constraint<_UTypes...>()) + && (__constructible<_UTypes...>()) + && (__dangles<_UTypes...>()) + tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete; + + template + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u) + : _Inherited(__tag, __a, static_cast(__u)) + { } + + template + requires (__constructible<_Elements...>()) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u)) + { } + + template + requires (__constructible()) + && (!__use_other_ctor&>()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UTypes...>& __u) + : _Inherited(__tag, __a, + static_cast&>(__u)) + { } + + template + requires (__constructible()) + && (!__use_other_ctor&>()) + && (__dangles()) + tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete; + + template + requires (__constructible<_UTypes...>()) + && (!__use_other_ctor>()) + && (!__dangles<_UTypes...>()) + constexpr explicit(!__use_other_ctor>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u)) + { } + + template + requires (__constructible<_UTypes...>()) + && (!__use_other_ctor>()) + && (__dangles<_UTypes...>()) + tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete; + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (__constructible<_UTypes&...>()) + && (!__use_other_ctor&>()) + && (!__dangles<_UTypes&...>()) + constexpr explicit(!__convertible<_UTypes&...>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u)) + { } + + template + requires (__constructible<_UTypes&...>()) + && (!__use_other_ctor&>()) + && (__dangles<_UTypes&...>()) + tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete; + + template + requires (__constructible()) + && (!__use_other_ctor>()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UTypes...>&& __u) + : _Inherited(__tag, __a, + static_cast&&>(__u)) + { } + + template + requires (__constructible()) + && (!__use_other_ctor>()) + && (__dangles()) + tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete; +#endif // C++23 + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __u) + noexcept(__nothrow_constructible()) + : _Inherited(__tag, __a, __u.first, __u.second) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (__dangles()) + tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete; + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1, _U2>()) + && (!__dangles<_U1, _U2>()) + constexpr explicit(!__convertible<_U1, _U2>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second)) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1, _U2>()) + && (__dangles<_U1, _U2>()) + tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete; + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1&, _U2&>()) + && (!__dangles<_U1&, _U2&>()) + constexpr explicit(!__convertible<_U1&, _U2&>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u) + noexcept(__nothrow_constructible<_U1&, _U2&>()) + : _Inherited(__tag, __a, __u.first, __u.second) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible<_U1&, _U2&>()) + && (__dangles<_U1&, _U2&>()) + tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete; + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (!__dangles()) + constexpr explicit(!__convertible()) + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>&& __u) + noexcept(__nothrow_constructible()) + : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second)) + { } + + template + requires (sizeof...(_Elements) == 2) + && (__constructible()) + && (__dangles()) + tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete; +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template _UTuple> + requires (__constructible_from_tuple_like<_UTuple>()) + && (!__use_other_ctor<_UTuple>()) + && (!__dangles_from_tuple_like<_UTuple>()) + constexpr explicit(!__convertible_from_tuple_like<_UTuple>()) + tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u) + : _Inherited(__tuple_like_tag_t{}, + __tag, __a, std::forward<_UTuple>(__u), + index_sequence_for<_Elements...>{}) + { } + + template _UTuple> + requires (__constructible_from_tuple_like<_UTuple>()) + && (!__use_other_ctor<_UTuple>()) + && (__dangles_from_tuple_like<_UTuple>()) + tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete; +#endif // C++23 + +#else // !(concepts && conditional_explicit) + + template + using _TCC = _TupleConstraints<_Cond, _Elements...>; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_explicitly_default_constructible(), + bool>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), + bool>; + + // Condition for noexcept-specifier of a constructor. + template + static constexpr bool __nothrow_constructible() + { + return + __and_...>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. + template + static constexpr bool __valid_args() + { + return sizeof...(_Elements) == 1 + && !is_same>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. + template + static constexpr bool __valid_args() + { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } + + /* Constraint for constructors with a tuple parameter ensures + * that the constructor is only viable when it would not interfere with + * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). + * Such constructors are only viable if: + * either sizeof...(Types) != 1, + * or (when Types... expands to T and UTypes... expands to U) + * is_convertible_v, is_constructible_v, + * and is_same_v are all false. + */ + template> + struct _UseOtherCtor + : false_type + { }; + // If TUPLE is convertible to the single element in *this, + // then TUPLE should match tuple(UTypes&&...) instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> + : __or_, is_constructible<_Tp, _Tuple>>::type + { }; + // If TUPLE and *this each have a single element of the same type, + // then TUPLE should match a copy/move constructor instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> + : true_type + { }; + + // Return true iff sizeof...(Types) == 1 && tuple_size_v == 1 + // and the single element in Types can be initialized from TUPLE, + // or is the same type as tuple_element_t<0, TUPLE>. + template + static constexpr bool __use_other_ctor() + { return _UseOtherCtor<_Tuple>::value; } + + /// @cond undocumented +#undef __glibcxx_no_dangling_refs +#if __has_builtin(__reference_constructs_from_temporary) \ + && defined _GLIBCXX_DEBUG + // Error if construction from U... would create a dangling ref. +# if __cpp_fold_expressions +# define __glibcxx_dangling_refs(U) \ + (__reference_constructs_from_temporary(_Elements, U) || ...) +# else +# define __glibcxx_dangling_refs(U) \ + __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \ + >...>::value +# endif +# define __glibcxx_no_dangling_refs(U) \ + static_assert(!__glibcxx_dangling_refs(U), \ + "std::tuple constructor creates a dangling reference") +#else +# define __glibcxx_no_dangling_refs(U) +#endif + /// @endcond + + public: + template::value> = true> + constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template::value> = false> + explicit constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + explicit constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) + { __glibcxx_no_dangling_refs(_UElements&&); } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) + { __glibcxx_no_dangling_refs(_UElements&&); } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _UElements&); } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + explicit constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _UElements&); } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { __glibcxx_no_dangling_refs(_UElements&&); } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { __glibcxx_no_dangling_refs(_UElements&&); } + + // Allocator-extended constructors. + + template::value> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template::value> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { __glibcxx_no_dangling_refs(_UElements&&); } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { __glibcxx_no_dangling_refs(_UElements&&); } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _UElements&); } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _UElements&); } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { __glibcxx_no_dangling_refs(_UElements&&); } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { __glibcxx_no_dangling_refs(_UElements&&); } +#endif // concepts && conditional_explicit + + // tuple assignment + +#if __cpp_concepts && __cpp_consteval // >= C++20 + private: + template + static consteval bool + __assignable() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } + + template + static consteval bool + __nothrow_assignable() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } + +#if __cpp_lib_ranges_zip // >= C++23 + template + static consteval bool + __const_assignable() + { + if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) + return __and_v...>; + else + return false; + } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template + static consteval bool + __assignable_from_tuple_like() + { + return [](index_sequence<_Is...>) { + return __assignable(std::declval<_UTuple>()))...>(); + }(index_sequence_for<_Elements...>{}); + } + + template + static consteval bool + __const_assignable_from_tuple_like() + { + return [](index_sequence<_Is...>) { + return __const_assignable(std::declval<_UTuple>()))...>(); + }(index_sequence_for<_Elements...>{}); + } +#endif // C++23 + + public: + + tuple& operator=(const tuple& __u) = delete; + + constexpr tuple& + operator=(const tuple& __u) + noexcept(__nothrow_assignable()) + requires (__assignable()) + { + this->_M_assign(__u); + return *this; + } + + constexpr tuple& + operator=(tuple&& __u) + noexcept(__nothrow_assignable<_Elements...>()) + requires (__assignable<_Elements...>()) + { + this->_M_assign(std::move(__u)); + return *this; + } + + template + requires (__assignable()) + constexpr tuple& + operator=(const tuple<_UTypes...>& __u) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__u); + return *this; + } + + template + requires (__assignable<_UTypes...>()) + constexpr tuple& + operator=(tuple<_UTypes...>&& __u) + noexcept(__nothrow_assignable<_UTypes...>()) + { + this->_M_assign(std::move(__u)); + return *this; + } + +#if __cpp_lib_ranges_zip // >= C++23 + constexpr const tuple& + operator=(const tuple& __u) const + requires (__const_assignable()) + { + this->_M_assign(__u); + return *this; + } + + constexpr const tuple& + operator=(tuple&& __u) const + requires (__const_assignable<_Elements...>()) + { + this->_M_assign(std::move(__u)); + return *this; + } + + template + constexpr const tuple& + operator=(const tuple<_UTypes...>& __u) const + requires (__const_assignable()) + { + this->_M_assign(__u); + return *this; + } + + template + constexpr const tuple& + operator=(tuple<_UTypes...>&& __u) const + requires (__const_assignable<_UTypes...>()) + { + this->_M_assign(std::move(__u)); + return *this; + } +#endif // C++23 + + template + requires (__assignable()) + constexpr tuple& + operator=(const pair<_U1, _U2>& __u) + noexcept(__nothrow_assignable()) + { + this->_M_head(*this) = __u.first; + this->_M_tail(*this)._M_head(*this) = __u.second; + return *this; + } + + template + requires (__assignable<_U1, _U2>()) + constexpr tuple& + operator=(pair<_U1, _U2>&& __u) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_head(*this) = std::forward<_U1>(__u.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second); + return *this; + } + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (__const_assignable()) + constexpr const tuple& + operator=(const pair<_U1, _U2>& __u) const + { + this->_M_head(*this) = __u.first; + this->_M_tail(*this)._M_head(*this) = __u.second; + return *this; + } + + template + requires (__const_assignable<_U1, _U2>()) + constexpr const tuple& + operator=(pair<_U1, _U2>&& __u) const + { + this->_M_head(*this) = std::forward<_U1>(__u.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second); + return *this; + } +#endif // C++23 + +#if __cpp_lib_tuple_like // >= C++23 + template<__eligible_tuple_like _UTuple> + requires (__assignable_from_tuple_like<_UTuple>()) + constexpr tuple& + operator=(_UTuple&& __u) + { + this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u)); + return *this; + } + + template<__eligible_tuple_like _UTuple> + requires (__const_assignable_from_tuple_like<_UTuple>()) + constexpr const tuple& + operator=(_UTuple&& __u) const + { + this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u)); + return *this; + } + + template<__tuple_like _UTuple> + requires (!__is_tuple_v<_UTuple>) + friend constexpr bool + operator==(const tuple& __t, const _UTuple& __u) + { + static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>, + "tuple objects can only be compared if they have equal sizes."); + return [&](index_sequence<_Is...>) { + return (bool(std::get<_Is>(__t) == std::get<_Is>(__u)) + && ...); + }(index_sequence_for<_Elements...>{}); + } + + template<__tuple_like _UTuple, + typename = make_index_sequence>> + struct __tuple_like_common_comparison_category; + + template<__tuple_like _UTuple, size_t... _Is> + requires requires + { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; } + struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>> + { + using type = common_comparison_category_t + <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; + }; + + template<__tuple_like _UTuple> + requires (!__is_tuple_v<_UTuple>) + friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type + operator<=>(const tuple& __t, const _UTuple& __u) + { + using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>()); + } +#endif // C++23 + +#else // ! (concepts && consteval) + + private: + template + static constexpr + __enable_if_t + __assignable() + { return __and_...>::value; } + + // Condition for noexcept-specifier of an assignment operator. + template + static constexpr bool __nothrow_assignable() + { + return + __and_...>::value; + } + + public: + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(__conditional_t<__assignable(), + const tuple&, + const __nonesuch&> __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(__conditional_t<__assignable<_Elements...>(), + tuple&&, + __nonesuch&&> __in) + noexcept(__nothrow_assignable<_Elements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_UElements...>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_UElements...>(), tuple&> + operator=(tuple<_UElements...>&& __in) + noexcept(__nothrow_assignable<_UElements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } +#endif // concepts && consteval + + // tuple swap + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) + { _Inherited::_M_swap(__in); } + +#if __cpp_lib_ranges_zip // >= C++23 + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of tuples whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. + constexpr void + swap(const tuple& __in) const + noexcept(__and_v<__is_nothrow_swappable...>) + requires (is_swappable_v && ...) + { _Inherited::_M_swap(__in); } +#endif // C++23 + }; + +#if __cpp_deduction_guides >= 201606 + template + tuple(_UTypes...) -> tuple<_UTypes...>; + template + tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; + template + tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; +#endif + + // Explicit specialization, zero-element tuple. + template<> + class tuple<> + { + public: + _GLIBCXX20_CONSTEXPR + void swap(tuple&) noexcept { /* no-op */ } +#if __cpp_lib_ranges_zip // >= C++23 + constexpr void swap(const tuple&) const noexcept { /* no-op */ } +#endif + // We need the default since we're going to define no-op + // allocator constructors. + tuple() = default; + // No-op allocator constructors. + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&) noexcept { } + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } + }; + +#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20 + /// Partial specialization, 2-element tuple. + /// Includes construction and assignment from a pair. + template + class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> + { + typedef _Tuple_impl<0, _T1, _T2> _Inherited; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_explicitly_default_constructible(), + bool>; + + template + using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), + bool>; + + template + static constexpr bool __assignable() + { + return __and_, + is_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_assignable() + { + return __and_, + is_nothrow_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_constructible() + { + return __and_, + is_nothrow_constructible<_T2, _U2>>::value; + } + + static constexpr bool __nothrow_default_constructible() + { + return __and_, + is_nothrow_default_constructible<_T2>>::value; + } + + template + static constexpr bool __is_alloc_arg() + { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } + + /// @cond undocumented +#undef __glibcxx_no_dangling_refs + // Error if construction from _U1 and _U2 would create a dangling ref. +#if __has_builtin(__reference_constructs_from_temporary) \ + && defined _GLIBCXX_DEBUG +# define __glibcxx_no_dangling_refs(_U1, _U2) \ + static_assert(!__reference_constructs_from_temporary(_T1, _U1) \ + && !__reference_constructs_from_temporary(_T2, _U2), \ + "std::tuple constructor creates a dangling reference") +#else +# define __glibcxx_no_dangling_refs(_U1, _U2) +#endif + /// @endcond + + public: + template = true> + constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = false> + explicit constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = true> + constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template = false> + explicit constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template(), _U1, _U2> = true> + constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template(), _U1, _U2> = false> + explicit constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template = true> + constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = false> + explicit constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = true> + constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = false> + explicit constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = true> + constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = false> + explicit constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = true> + constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = false> + explicit constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + // Allocator-extended constructors. + + template::value, _T1, _T2> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template::value, _T1, _T2> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) + { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) + { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } + + // Tuple assignment. + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(__conditional_t<__assignable(), + const tuple&, + const __nonesuch&> __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(__conditional_t<__assignable<_T1, _T2>(), + tuple&&, + __nonesuch&&> __in) + noexcept(__nothrow_assignable<_T1, _T2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const pair<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(pair<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); + return *this; + } + + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { _Inherited::_M_swap(__in); } + }; +#endif // concepts && conditional_explicit + + /// class tuple_size + template + struct tuple_size> + : public integral_constant { }; + +#if __cplusplus >= 201703L + template + inline constexpr size_t tuple_size_v> + = sizeof...(_Types); + + template + inline constexpr size_t tuple_size_v> + = sizeof...(_Types); +#endif + + /// Trait to get the Ith element type from a tuple. + template + struct tuple_element<__i, tuple<_Types...>> + { + static_assert(__i < sizeof...(_Types), "tuple index must be in range"); + + using type = typename _Nth_type<__i, _Types...>::type; + }; + + template + constexpr _Head& + __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + template + constexpr const _Head& + __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + // Deleted overload to improve diagnostics for invalid indices + template + __enable_if_t<(__i >= sizeof...(_Types))> + __get_helper(const tuple<_Types...>&) = delete; + + /// Return a reference to the ith element of a tuple. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>& + get(tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return a const reference to the ith element of a const tuple. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>& + get(const tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return an rvalue reference to the ith element of a tuple rvalue. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>&& + get(tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward<__element_type>(std::__get_helper<__i>(__t)); + } + + /// Return a const rvalue reference to the ith element of a const tuple rvalue. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& + get(const tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward(std::__get_helper<__i>(__t)); + } + + /// @cond undocumented + // Deleted overload chosen for invalid indices. + template + constexpr __enable_if_t<(__i >= sizeof...(_Elements))> + get(const tuple<_Elements...>&) = delete; + /// @endcond + +#ifdef __cpp_lib_tuples_by_type // C++ >= 14 + /// Return a reference to the unique element of type _Tp of a tuple. + template + constexpr _Tp& + get(tuple<_Types...>& __t) noexcept + { + constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>(); + static_assert(__idx < sizeof...(_Types), + "the type T in std::get must occur exactly once in the tuple"); + return std::__get_helper<__idx>(__t); + } + + /// Return a reference to the unique element of type _Tp of a tuple rvalue. + template + constexpr _Tp&& + get(tuple<_Types...>&& __t) noexcept + { + constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>(); + static_assert(__idx < sizeof...(_Types), + "the type T in std::get must occur exactly once in the tuple"); + return std::forward<_Tp>(std::__get_helper<__idx>(__t)); + } + + /// Return a const reference to the unique element of type _Tp of a tuple. + template + constexpr const _Tp& + get(const tuple<_Types...>& __t) noexcept + { + constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>(); + static_assert(__idx < sizeof...(_Types), + "the type T in std::get must occur exactly once in the tuple"); + return std::__get_helper<__idx>(__t); + } + + /// Return a const reference to the unique element of type _Tp of + /// a const tuple rvalue. + template + constexpr const _Tp&& + get(const tuple<_Types...>&& __t) noexcept + { + constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>(); + static_assert(__idx < sizeof...(_Types), + "the type T in std::get must occur exactly once in the tuple"); + return std::forward(std::__get_helper<__idx>(__t)); + } +#endif + + // This class performs the comparison operations on tuples + template + struct __tuple_compare + { + static constexpr bool + __eq(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) == std::get<__i>(__u)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); + } + + static constexpr bool + __less(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) < std::get<__i>(__u)) + || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); + } + }; + + template + struct __tuple_compare<_Tp, _Up, __size, __size> + { + static constexpr bool + __eq(const _Tp&, const _Up&) { return true; } + + static constexpr bool + __less(const _Tp&, const _Up&) { return false; } + }; + + template + constexpr bool + operator==(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__eq(__t, __u); + } + +#if __cpp_lib_three_way_comparison + template + constexpr _Cat + __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) + { return _Cat::equivalent; } + + template + constexpr _Cat + __tuple_cmp(const _Tp& __t, const _Up& __u, + index_sequence<_Idx0, _Idxs...>) + { + auto __c + = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); + if (__c != 0) + return __c; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); + } + + template + constexpr + common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> + operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) + { + using _Cat + = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); + } +#else + template + constexpr bool + operator<(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__less(__t, __u); + } + + template + constexpr bool + operator!=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t == __u); } + + template + constexpr bool + operator>(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return __u < __t; } + + template + constexpr bool + operator<=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__u < __t); } + + template + constexpr bool + operator>=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t < __u); } +#endif // three_way_comparison + + // NB: DR 705. + /// Create a tuple containing copies of the arguments + template + constexpr tuple::__type...> + make_tuple(_Elements&&... __args) + { + typedef tuple::__type...> + __result_type; + return __result_type(std::forward<_Elements>(__args)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2275. Why is forward_as_tuple not constexpr? + /// Create a tuple of lvalue or rvalue references to the arguments + template + constexpr tuple<_Elements&&...> + forward_as_tuple(_Elements&&... __args) noexcept + { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } + + /// @cond undocumented + template + struct __make_tuple_impl; + + template + struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> + : __make_tuple_impl<_Idx + 1, + tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, + _Tuple, _Nm> + { }; + + template + struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> + { + typedef tuple<_Tp...> __type; + }; + + template + struct __do_make_tuple + : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value> + { }; + + // Returns the std::tuple equivalent of a tuple-like type. + template + struct __make_tuple + : public __do_make_tuple<__remove_cvref_t<_Tuple>> + { }; + + // Combines several std::tuple's into a single one. + template + struct __combine_tuples; + + template<> + struct __combine_tuples<> + { + typedef tuple<> __type; + }; + + template + struct __combine_tuples> + { + typedef tuple<_Ts...> __type; + }; + + template + struct __combine_tuples, tuple<_T2s...>, _Rem...> + { + typedef typename __combine_tuples, + _Rem...>::__type __type; + }; + + // Computes the result type of tuple_cat given a set of tuple-like types. + template + struct __tuple_cat_result + { + typedef typename __combine_tuples + ::__type...>::__type __type; + }; + + // Helper to determine the index set for the first tuple-like + // type of a given set. + template + struct __make_1st_indices; + + template<> + struct __make_1st_indices<> + { + typedef _Index_tuple<> __type; + }; + + template + struct __make_1st_indices<_Tp, _Tpls...> + { + typedef typename _Build_index_tuple::type>::value>::__type __type; + }; + + // Performs the actual concatenation by step-wise expanding tuple-like + // objects into the elements, which are finally forwarded into the + // result tuple. + template + struct __tuple_concater; + + template + struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...> + { + template + static constexpr _Ret + _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) + { + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; + return __next::_S_do(std::forward<_Tpls>(__tps)..., + std::forward<_Us>(__us)..., + std::get<_Is>(std::forward<_Tp>(__tp))...); + } + }; + + template + struct __tuple_concater<_Ret, _Index_tuple<>> + { + template + static constexpr _Ret + _S_do(_Us&&... __us) + { + return _Ret(std::forward<_Us>(__us)...); + } + }; + + template + struct __is_tuple_like_impl> : true_type + { }; + /// @endcond + + /// Create a `tuple` containing all elements from multiple tuple-like objects +#if __cpp_lib_tuple_like // >= C++23 + template<__tuple_like... _Tpls> +#else + template...>::value>::type> +#endif + constexpr auto + tuple_cat(_Tpls&&... __tpls) + -> typename __tuple_cat_result<_Tpls...>::__type + { + typedef typename __tuple_cat_result<_Tpls...>::__type __ret; + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; + return __concater::_S_do(std::forward<_Tpls>(__tpls)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2301. Why is tie not constexpr? + /// Return a tuple of lvalue references bound to the arguments + template + constexpr tuple<_Elements&...> + tie(_Elements&... __args) noexcept + { return tuple<_Elements&...>(__args...); } + + /// Exchange the values of two tuples + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Elements>...>::value + >::type +#else + void +#endif + swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __cpp_lib_ranges_zip // >= C++23 + template + requires (is_swappable_v && ...) + constexpr void + swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } +#endif // C++23 + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + /// Exchange the values of two const tuples (if const elements can be swapped) + template + _GLIBCXX20_CONSTEXPR + typename enable_if...>::value>::type + swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; +#endif + + // A class (and instance) which can be used in 'tie' when an element + // of a tuple is not required. + // _GLIBCXX14_CONSTEXPR + // 2933. PR for LWG 2773 could be clearer + struct _Swallow_assign + { + template + _GLIBCXX14_CONSTEXPR const _Swallow_assign& + operator=(const _Tp&) const + { return *this; } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2773. Making std::ignore constexpr + /** Used with `std::tie` to ignore an element of a tuple + * + * When using `std::tie` to assign the elements of a tuple to variables, + * unwanted elements can be ignored by using `std::ignore`. For example: + * + * ``` + * int x, y; + * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3); + * ``` + * + * This assignment will perform `x=1; std::ignore=2; y=3;` which results + * in the second element being ignored. + * + * @since C++11 + */ + _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; + + /// Partial specialization for tuples + template + struct uses_allocator, _Alloc> : true_type { }; + + // See stl_pair.h... + /** "piecewise construction" using a tuple of arguments for each member. + * + * @param __first Arguments for the first member of the pair. + * @param __second Arguments for the second member of the pair. + * + * The elements of each tuple will be used as the constructor arguments + * for the data members of the pair. + */ + template + template + _GLIBCXX20_CONSTEXPR + inline + pair<_T1, _T2>:: + pair(piecewise_construct_t, + tuple<_Args1...> __first, tuple<_Args2...> __second) + : pair(__first, __second, + typename _Build_index_tuple::__type(), + typename _Build_index_tuple::__type()) + { } + + template + template + _GLIBCXX20_CONSTEXPR inline + pair<_T1, _T2>:: + pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) + : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), + second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) + { } + +#if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17 + // Unpack a std::tuple into a type trait and use its value. + // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. + // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. + // Otherwise the result is false (because we don't know if std::get throws). + template class _Trait, typename _Tp, typename _Tuple> + inline constexpr bool __unpack_std_tuple = false; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> + = _Trait<_Tp, _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> + = _Trait<_Tp, _Up&...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> + = _Trait<_Tp, const _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> + = _Trait<_Tp, const _Up&...>::value; +#endif + +#ifdef __cpp_lib_apply // C++ >= 17 + template + constexpr decltype(auto) + __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) + { + return std::__invoke(std::forward<_Fn>(__f), + std::get<_Idx>(std::forward<_Tuple>(__t))...); + } + +#if __cpp_lib_tuple_like // >= C++23 + template +#else + template +#endif + constexpr decltype(auto) + apply(_Fn&& __f, _Tuple&& __t) + noexcept(__unpack_std_tuple) + { + using _Indices + = make_index_sequence>>; + return std::__apply_impl(std::forward<_Fn>(__f), + std::forward<_Tuple>(__t), + _Indices{}); + } +#endif + +#ifdef __cpp_lib_make_from_tuple // C++ >= 17 + template + constexpr _Tp + __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) + { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } + +#if __cpp_lib_tuple_like // >= C++23 + template +#else + template +#endif + constexpr _Tp + make_from_tuple(_Tuple&& __t) + noexcept(__unpack_std_tuple) + { + constexpr size_t __n = tuple_size_v>; +#if __has_builtin(__reference_constructs_from_temporary) + if constexpr (__n == 1) + { + using _Elt = decltype(std::get<0>(std::declval<_Tuple>())); + static_assert(!__reference_constructs_from_temporary(_Tp, _Elt)); + } +#endif + return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t), + make_index_sequence<__n>{}); + } +#endif + +#if __cpp_lib_tuple_like // >= C++23 + template<__tuple_like _TTuple, __tuple_like _UTuple, + template class _TQual, template class _UQual, + typename = make_index_sequence>> + struct __tuple_like_common_reference; + + template<__tuple_like _TTuple, __tuple_like _UTuple, + template class _TQual, template class _UQual, + size_t... _Is> + requires requires + { typename tuple>, + _UQual>>...>; } + struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>> + { + using type = tuple>, + _UQual>>...>; + }; + + template<__tuple_like _TTuple, __tuple_like _UTuple, + template class _TQual, template class _UQual> + requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>) + && is_same_v<_TTuple, decay_t<_TTuple>> + && is_same_v<_UTuple, decay_t<_UTuple>> + && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>) + && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; } + struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual> + { + using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; + }; + + template<__tuple_like _TTuple, __tuple_like _UTuple, + typename = make_index_sequence>> + struct __tuple_like_common_type; + + template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is> + requires requires + { typename tuple, + tuple_element_t<_Is, _UTuple>>...>; } + struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>> + { + using type = tuple, + tuple_element_t<_Is, _UTuple>>...>; + }; + + template<__tuple_like _TTuple, __tuple_like _UTuple> + requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>) + && is_same_v<_TTuple, decay_t<_TTuple>> + && is_same_v<_UTuple, decay_t<_UTuple>> + && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>) + && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; } + struct common_type<_TTuple, _UTuple> + { + using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type; + }; +#endif // C++23 + + /// @} + +#undef __glibcxx_no_dangling_refs + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TUPLE diff --git a/template/sysroot/include/type_traits b/template/sysroot/include/type_traits new file mode 100644 index 0000000..b441bf9 --- /dev/null +++ b/template/sysroot/include/type_traits @@ -0,0 +1,4007 @@ +// C++11 -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/type_traits + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPE_TRAITS +#define _GLIBCXX_TYPE_TRAITS 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#define __glibcxx_want_bool_constant +#define __glibcxx_want_bounded_array_traits +#define __glibcxx_want_has_unique_object_representations +#define __glibcxx_want_integral_constant_callable +#define __glibcxx_want_is_aggregate +#define __glibcxx_want_is_constant_evaluated +#define __glibcxx_want_is_final +#define __glibcxx_want_is_invocable +#define __glibcxx_want_is_layout_compatible +#define __glibcxx_want_is_nothrow_convertible +#define __glibcxx_want_is_null_pointer +#define __glibcxx_want_is_pointer_interconvertible +#define __glibcxx_want_is_scoped_enum +#define __glibcxx_want_is_swappable +#define __glibcxx_want_logical_traits +#define __glibcxx_want_reference_from_temporary +#define __glibcxx_want_remove_cvref +#define __glibcxx_want_result_of_sfinae +#define __glibcxx_want_transformation_trait_aliases +#define __glibcxx_want_type_identity +#define __glibcxx_want_type_trait_variable_templates +#define __glibcxx_want_unwrap_ref +#define __glibcxx_want_void_t +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + class reference_wrapper; + + /** + * @defgroup metaprogramming Metaprogramming + * @ingroup utilities + * + * Template utilities for compile-time introspection and modification, + * including type classification traits, type property inspection traits + * and type transformation traits. + * + * @since C++11 + * + * @{ + */ + + /// integral_constant + template + struct integral_constant + { + static constexpr _Tp value = __v; + using value_type = _Tp; + using type = integral_constant<_Tp, __v>; + constexpr operator value_type() const noexcept { return value; } + +#ifdef __cpp_lib_integral_constant_callable // C++ >= 14 + constexpr value_type operator()() const noexcept { return value; } +#endif + }; + +#if ! __cpp_inline_variables + template + constexpr _Tp integral_constant<_Tp, __v>::value; +#endif + + /// @cond undocumented + /// bool_constant for C++11 + template + using __bool_constant = integral_constant; + /// @endcond + + /// The type used as a compile-time boolean with true value. + using true_type = __bool_constant; + + /// The type used as a compile-time boolean with false value. + using false_type = __bool_constant; + +#ifdef __cpp_lib_bool_constant // C++ >= 17 + /// Alias template for compile-time boolean constant types. + /// @since C++17 + template + using bool_constant = __bool_constant<__v>; +#endif + + // Metaprogramming helper types. + + // Primary template. + /// Define a member typedef `type` only if a boolean constant is true. + template + struct enable_if + { }; + + // Partial specialization for true. + template + struct enable_if + { using type = _Tp; }; + + // __enable_if_t (std::enable_if_t for C++11) + template + using __enable_if_t = typename enable_if<_Cond, _Tp>::type; + + template + struct __conditional + { + template + using type = _Tp; + }; + + template<> + struct __conditional + { + template + using type = _Up; + }; + + // More efficient version of std::conditional_t for internal use (and C++11) + template + using __conditional_t + = typename __conditional<_Cond>::template type<_If, _Else>; + + /// @cond undocumented + template + struct __type_identity + { using type = _Type; }; + + template + using __type_identity_t = typename __type_identity<_Tp>::type; + + namespace __detail + { + // A variadic alias template that resolves to its first argument. + template + using __first_t = _Tp; + + // These are deliberately not defined. + template + auto __or_fn(int) -> __first_t...>; + + template + auto __or_fn(...) -> true_type; + + template + auto __and_fn(int) -> __first_t...>; + + template + auto __and_fn(...) -> false_type; + } // namespace detail + + // Like C++17 std::dis/conjunction, but usable in C++11 and resolves + // to either true_type or false_type which allows for a more efficient + // implementation that avoids recursive class template instantiation. + template + struct __or_ + : decltype(__detail::__or_fn<_Bn...>(0)) + { }; + + template + struct __and_ + : decltype(__detail::__and_fn<_Bn...>(0)) + { }; + + template + struct __not_ + : __bool_constant + { }; + /// @endcond + +#ifdef __cpp_lib_logical_traits // C++ >= 17 + + /// @cond undocumented + template + inline constexpr bool __or_v = __or_<_Bn...>::value; + template + inline constexpr bool __and_v = __and_<_Bn...>::value; + + namespace __detail + { + template + struct __disjunction_impl + { using type = _B1; }; + + template + struct __disjunction_impl<__enable_if_t, _B1, _B2, _Bn...> + { using type = typename __disjunction_impl::type; }; + + template + struct __conjunction_impl + { using type = _B1; }; + + template + struct __conjunction_impl<__enable_if_t, _B1, _B2, _Bn...> + { using type = typename __conjunction_impl::type; }; + } // namespace __detail + /// @endcond + + template + struct conjunction + : __detail::__conjunction_impl::type + { }; + + template<> + struct conjunction<> + : true_type + { }; + + template + struct disjunction + : __detail::__disjunction_impl::type + { }; + + template<> + struct disjunction<> + : false_type + { }; + + template + struct negation + : __not_<_Pp>::type + { }; + + /** @ingroup variable_templates + * @{ + */ + template + inline constexpr bool conjunction_v = conjunction<_Bn...>::value; + + template + inline constexpr bool disjunction_v = disjunction<_Bn...>::value; + + template + inline constexpr bool negation_v = negation<_Pp>::value; + /// @} + +#endif // __cpp_lib_logical_traits + + // Forward declarations + template + struct is_reference; + template + struct is_function; + template + struct is_void; + template + struct remove_cv; + template + struct is_const; + + /// @cond undocumented + template + struct __is_array_unknown_bounds; + + // Helper functions that return false_type for incomplete classes, + // incomplete unions and arrays of known bound from those. + + template + constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) + { return {}; } + + template + constexpr typename __or_< + is_reference<_NestedType>, + is_function<_NestedType>, + is_void<_NestedType>, + __is_array_unknown_bounds<_NestedType> + >::type __is_complete_or_unbounded(_TypeIdentity) + { return {}; } + + // __remove_cv_t (std::remove_cv_t for C++11). + template + using __remove_cv_t = typename remove_cv<_Tp>::type; + /// @endcond + + // Primary type categories. + + /// is_void + template + struct is_void + : public false_type { }; + + template<> + struct is_void + : public true_type { }; + + template<> + struct is_void + : public true_type { }; + + template<> + struct is_void + : public true_type { }; + + template<> + struct is_void + : public true_type { }; + + /// @cond undocumented + template + struct __is_integral_helper + : public false_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + // We want is_integral to be true (and make_signed/unsigned to work) + // even when libc doesn't provide working and related functions, + // so don't check _GLIBCXX_USE_WCHAR_T here. + template<> + struct __is_integral_helper + : public true_type { }; + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integral_helper + : public true_type { }; +#endif + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + // Conditionalizing on __STRICT_ANSI__ here will break any port that + // uses one of these types for size_t. +#if defined(__GLIBCXX_TYPE_INT_N_0) + __extension__ + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0> + : public true_type { }; + + __extension__ + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + __extension__ + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1> + : public true_type { }; + + __extension__ + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + __extension__ + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2> + : public true_type { }; + + __extension__ + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + __extension__ + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3> + : public true_type { }; + + __extension__ + template<> + struct __is_integral_helper + : public true_type { }; +#endif + /// @endcond + + /// is_integral + template + struct is_integral + : public __is_integral_helper<__remove_cv_t<_Tp>>::type + { }; + + /// @cond undocumented + template + struct __is_floating_point_helper + : public false_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __is_floating_point_helper<_Float16> + : public true_type { }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __is_floating_point_helper<_Float32> + : public true_type { }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __is_floating_point_helper<_Float64> + : public true_type { }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __is_floating_point_helper<_Float128> + : public true_type { }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t> + : public true_type { }; +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + struct __is_floating_point_helper<__float128> + : public true_type { }; +#endif + /// @endcond + + /// is_floating_point + template + struct is_floating_point + : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_array +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array) + template + struct is_array + : public __bool_constant<__is_array(_Tp)> + { }; +#else + template + struct is_array + : public false_type { }; + + template + struct is_array<_Tp[_Size]> + : public true_type { }; + + template + struct is_array<_Tp[]> + : public true_type { }; +#endif + + template + struct __is_pointer_helper + : public false_type { }; + + template + struct __is_pointer_helper<_Tp*> + : public true_type { }; + + /// is_pointer + template + struct is_pointer + : public __is_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_lvalue_reference + template + struct is_lvalue_reference + : public false_type { }; + + template + struct is_lvalue_reference<_Tp&> + : public true_type { }; + + /// is_rvalue_reference + template + struct is_rvalue_reference + : public false_type { }; + + template + struct is_rvalue_reference<_Tp&&> + : public true_type { }; + + /// is_member_object_pointer +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer) + template + struct is_member_object_pointer + : public __bool_constant<__is_member_object_pointer(_Tp)> + { }; +#else + template + struct __is_member_object_pointer_helper + : public false_type { }; + + template + struct __is_member_object_pointer_helper<_Tp _Cp::*> + : public __not_>::type { }; + + + template + struct is_member_object_pointer + : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type + { }; +#endif + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer) + /// is_member_function_pointer + template + struct is_member_function_pointer + : public __bool_constant<__is_member_function_pointer(_Tp)> + { }; +#else + template + struct __is_member_function_pointer_helper + : public false_type { }; + + template + struct __is_member_function_pointer_helper<_Tp _Cp::*> + : public is_function<_Tp>::type { }; + + /// is_member_function_pointer + template + struct is_member_function_pointer + : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type + { }; +#endif + + /// is_enum + template + struct is_enum + : public __bool_constant<__is_enum(_Tp)> + { }; + + /// is_union + template + struct is_union + : public __bool_constant<__is_union(_Tp)> + { }; + + /// is_class + template + struct is_class + : public __bool_constant<__is_class(_Tp)> + { }; + + /// is_function +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) + template + struct is_function + : public __bool_constant<__is_function(_Tp)> + { }; +#else + template + struct is_function + : public __bool_constant::value> { }; + + template + struct is_function<_Tp&> + : public false_type { }; + + template + struct is_function<_Tp&&> + : public false_type { }; +#endif + +#ifdef __cpp_lib_is_null_pointer // C++ >= 11 + /// is_null_pointer (LWG 2247). + template + struct is_null_pointer + : public false_type { }; + + template<> + struct is_null_pointer + : public true_type { }; + + template<> + struct is_null_pointer + : public true_type { }; + + template<> + struct is_null_pointer + : public true_type { }; + + template<> + struct is_null_pointer + : public true_type { }; + + /// __is_nullptr_t (deprecated extension). + /// @deprecated Non-standard. Use `is_null_pointer` instead. + template + struct __is_nullptr_t + : public is_null_pointer<_Tp> + { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer"); +#endif // __cpp_lib_is_null_pointer + + // Composite type categories. + + /// is_reference +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference) + template + struct is_reference + : public __bool_constant<__is_reference(_Tp)> + { }; +#else + template + struct is_reference + : public false_type + { }; + + template + struct is_reference<_Tp&> + : public true_type + { }; + + template + struct is_reference<_Tp&&> + : public true_type + { }; +#endif + + /// is_arithmetic + template + struct is_arithmetic + : public __or_, is_floating_point<_Tp>>::type + { }; + + /// is_fundamental + template + struct is_fundamental + : public __or_, is_void<_Tp>, + is_null_pointer<_Tp>>::type + { }; + + /// is_object +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object) + template + struct is_object + : public __bool_constant<__is_object(_Tp)> + { }; +#else + template + struct is_object + : public __not_<__or_, is_reference<_Tp>, + is_void<_Tp>>>::type + { }; +#endif + + template + struct is_member_pointer; + + /// is_scalar + template + struct is_scalar + : public __or_, is_enum<_Tp>, is_pointer<_Tp>, + is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type + { }; + + /// is_compound + template + struct is_compound + : public __bool_constant::value> { }; + + /// is_member_pointer +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer) + template + struct is_member_pointer + : public __bool_constant<__is_member_pointer(_Tp)> + { }; +#else + /// @cond undocumented + template + struct __is_member_pointer_helper + : public false_type { }; + + template + struct __is_member_pointer_helper<_Tp _Cp::*> + : public true_type { }; + /// @endcond + + template + struct is_member_pointer + : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type + { }; +#endif + + template + struct is_same; + + /// @cond undocumented + template + using __is_one_of = __or_...>; + + // Check if a type is one of the signed integer types. + __extension__ + template + using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, + signed char, signed short, signed int, signed long, + signed long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , signed __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , signed __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , signed __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , signed __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the unsigned integer types. + __extension__ + template + using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , unsigned __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , unsigned __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , unsigned __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , unsigned __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the signed or unsigned integer types. + template + using __is_standard_integer + = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; + + // __void_t (std::void_t for C++11) + template using __void_t = void; + /// @endcond + + // Type properties. + + /// is_const + template + struct is_const + : public false_type { }; + + template + struct is_const<_Tp const> + : public true_type { }; + + /// is_volatile + template + struct is_volatile + : public false_type { }; + + template + struct is_volatile<_Tp volatile> + : public true_type { }; + + /// is_trivial + template + struct is_trivial + : public __bool_constant<__is_trivial(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_copyable + template + struct is_trivially_copyable + : public __bool_constant<__is_trivially_copyable(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_standard_layout + template + struct is_standard_layout + : public __bool_constant<__is_standard_layout(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /** is_pod + * @deprecated Deprecated in C++20. + * Use `is_standard_layout && is_trivial` instead. + */ + // Could use is_standard_layout && is_trivial instead of the builtin. + template + struct + _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial") + is_pod + : public __bool_constant<__is_pod(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /** is_literal_type + * @deprecated Deprecated in C++17, removed in C++20. + * The idea of a literal type isn't useful. + */ + template + struct + _GLIBCXX17_DEPRECATED + is_literal_type + : public __bool_constant<__is_literal_type(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_empty + template + struct is_empty + : public __bool_constant<__is_empty(_Tp)> + { }; + + /// is_polymorphic + template + struct is_polymorphic + : public __bool_constant<__is_polymorphic(_Tp)> + { }; + +#ifdef __cpp_lib_is_final // C++ >= 14 + /// is_final + /// @since C++14 + template + struct is_final + : public __bool_constant<__is_final(_Tp)> + { }; +#endif + + /// is_abstract + template + struct is_abstract + : public __bool_constant<__is_abstract(_Tp)> + { }; + + /// @cond undocumented + template::value> + struct __is_signed_helper + : public false_type { }; + + template + struct __is_signed_helper<_Tp, true> + : public __bool_constant<_Tp(-1) < _Tp(0)> + { }; + /// @endcond + + /// is_signed + template + struct is_signed + : public __is_signed_helper<_Tp>::type + { }; + + /// is_unsigned + template + struct is_unsigned + : public __and_, __not_>>::type + { }; + + /// @cond undocumented + template + _Up + __declval(int); + + template + _Tp + __declval(long); + /// @endcond + + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)); + + template + struct remove_all_extents; + + /// @cond undocumented + template + struct __is_array_known_bounds + : public false_type + { }; + + template + struct __is_array_known_bounds<_Tp[_Size]> + : public true_type + { }; + + template + struct __is_array_unknown_bounds + : public false_type + { }; + + template + struct __is_array_unknown_bounds<_Tp[]> + : public true_type + { }; + + // Destructible and constructible type properties. + + // In N3290 is_destructible does not say anything about function + // types and abstract types, see LWG 2049. This implementation + // describes function types as non-destructible and all complete + // object types as destructible, iff the explicit destructor + // call expression is wellformed. + struct __do_is_destructible_impl + { + template().~_Tp())> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_destructible_impl + : public __do_is_destructible_impl + { + using type = decltype(__test<_Tp>(0)); + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_destructible_safe; + + template + struct __is_destructible_safe<_Tp, false, false> + : public __is_destructible_impl::type>::type + { }; + + template + struct __is_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_destructible_safe<_Tp, false, true> + : public true_type { }; + /// @endcond + + /// is_destructible + template + struct is_destructible + : public __is_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + + // is_nothrow_destructible requires that is_destructible is + // satisfied as well. We realize that by mimicing the + // implementation of is_destructible but refer to noexcept(expr) + // instead of decltype(expr). + struct __do_is_nt_destructible_impl + { + template + static __bool_constant().~_Tp())> + __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_nt_destructible_impl + : public __do_is_nt_destructible_impl + { + using type = decltype(__test<_Tp>(0)); + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_nt_destructible_safe; + + template + struct __is_nt_destructible_safe<_Tp, false, false> + : public __is_nt_destructible_impl::type>::type + { }; + + template + struct __is_nt_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_nt_destructible_safe<_Tp, false, true> + : public true_type { }; + /// @endcond + + /// is_nothrow_destructible + template + struct is_nothrow_destructible + : public __is_nt_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_constructible_impl + = __bool_constant<__is_constructible(_Tp, _Args...)>; + /// @endcond + + /// is_constructible + template + struct is_constructible + : public __is_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_default_constructible + template + struct is_default_constructible + : public __is_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + struct __add_lvalue_reference_helper + { using type = _Tp; }; + + template + struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>> + { using type = _Tp&; }; + + template + using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type; + /// @endcond + + /// is_copy_constructible + template + struct is_copy_constructible + : public __is_constructible_impl<_Tp, __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + struct __add_rvalue_reference_helper + { using type = _Tp; }; + + template + struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>> + { using type = _Tp&&; }; + + template + using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type; + /// @endcond + + /// is_move_constructible + template + struct is_move_constructible + : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_nothrow_constructible_impl + = __bool_constant<__is_nothrow_constructible(_Tp, _Args...)>; + /// @endcond + + /// is_nothrow_constructible + template + struct is_nothrow_constructible + : public __is_nothrow_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_default_constructible + template + struct is_nothrow_default_constructible + : public __is_nothrow_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible + : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_move_constructible + template + struct is_nothrow_move_constructible + : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>; + /// @endcond + + /// is_assignable + template + struct is_assignable + : public __is_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_copy_assignable + template + struct is_copy_assignable + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_move_assignable + template + struct is_move_assignable + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_nothrow_assignable_impl + = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>; + /// @endcond + + /// is_nothrow_assignable + template + struct is_nothrow_assignable + : public __is_nothrow_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_move_assignable + template + struct is_nothrow_move_assignable + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_trivially_constructible_impl + = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>; + /// @endcond + + /// is_trivially_constructible + template + struct is_trivially_constructible + : public __is_trivially_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_default_constructible + template + struct is_trivially_default_constructible + : public __is_trivially_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __cpp_variable_templates && __cpp_concepts + template + constexpr bool __is_implicitly_default_constructible_v + = requires (void(&__f)(_Tp)) { __f({}); }; + + template + struct __is_implicitly_default_constructible + : __bool_constant<__is_implicitly_default_constructible_v<_Tp>> + { }; +#else + struct __do_is_implicitly_default_constructible_impl + { + template + static void __helper(const _Tp&); + + template + static true_type __test(const _Tp&, + decltype(__helper({}))* = 0); + + static false_type __test(...); + }; + + template + struct __is_implicitly_default_constructible_impl + : public __do_is_implicitly_default_constructible_impl + { + using type = decltype(__test(declval<_Tp>())); + }; + + template + struct __is_implicitly_default_constructible_safe + : public __is_implicitly_default_constructible_impl<_Tp>::type + { }; + + template + struct __is_implicitly_default_constructible + : public __and_<__is_constructible_impl<_Tp>, + __is_implicitly_default_constructible_safe<_Tp>>::type + { }; +#endif + + /// is_trivially_copy_constructible + template + struct is_trivially_copy_constructible + : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_move_constructible + template + struct is_trivially_move_constructible + : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + template + using __is_trivially_assignable_impl + = __bool_constant<__is_trivially_assignable(_Tp, _Up)>; + /// @endcond + + /// is_trivially_assignable + template + struct is_trivially_assignable + : public __is_trivially_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_copy_assignable + template + struct is_trivially_copy_assignable + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_move_assignable + template + struct is_trivially_move_assignable + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_destructible + template + struct is_trivially_destructible + : public __and_<__is_destructible_safe<_Tp>, + __bool_constant<__has_trivial_destructor(_Tp)>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + /// has_virtual_destructor + template + struct has_virtual_destructor + : public __bool_constant<__has_virtual_destructor(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + // type property queries. + + /// alignment_of + template + struct alignment_of + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// rank + template + struct rank + : public integral_constant { }; + + template + struct rank<_Tp[_Size]> + : public integral_constant::value> { }; + + template + struct rank<_Tp[]> + : public integral_constant::value> { }; + + /// extent + template + struct extent + : public integral_constant { }; + + template + struct extent<_Tp[_Size], 0> + : public integral_constant { }; + + template + struct extent<_Tp[_Size], _Uint> + : public extent<_Tp, _Uint - 1>::type { }; + + template + struct extent<_Tp[], 0> + : public integral_constant { }; + + template + struct extent<_Tp[], _Uint> + : public extent<_Tp, _Uint - 1>::type { }; + + + // Type relations. + + /// is_same +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same) + template + struct is_same + : public __bool_constant<__is_same(_Tp, _Up)> + { }; +#else + template + struct is_same + : public false_type + { }; + + template + struct is_same<_Tp, _Tp> + : public true_type + { }; +#endif + + /// is_base_of + template + struct is_base_of + : public __bool_constant<__is_base_of(_Base, _Derived)> + { }; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible) + template + struct is_convertible + : public __bool_constant<__is_convertible(_From, _To)> + { }; +#else + template, is_function<_To>, + is_array<_To>>::value> + struct __is_convertible_helper + { + using type = typename is_void<_To>::type; + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template(std::declval<_From1>()))> + static true_type + __test(int); + + template + static false_type + __test(...); + + public: + using type = decltype(__test<_From, _To>(0)); + }; +#pragma GCC diagnostic pop + + /// is_convertible + template + struct is_convertible + : public __is_convertible_helper<_From, _To>::type + { }; +#endif + + // helper trait for unique_ptr, shared_ptr, and span + template + using __is_array_convertible + = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>; + +#ifdef __cpp_lib_is_nothrow_convertible // C++ >= 20 + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_convertible) + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = __is_nothrow_convertible(_From, _To); + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public bool_constant> + { }; +#else + template, is_function<_To>, + is_array<_To>>::value> + struct __is_nt_convertible_helper + : is_void<_To> + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_nt_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template + static + __bool_constant(std::declval<_From1>()))> + __test(int); + + template + static false_type + __test(...); + + public: + using type = decltype(__test<_From, _To>(0)); + }; +#pragma GCC diagnostic pop + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public __is_nt_convertible_helper<_From, _To>::type + { }; + + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = is_nothrow_convertible<_From, _To>::value; +#endif +#endif // __cpp_lib_is_nothrow_convertible + + // Const-volatile modifications. + + /// remove_const + template + struct remove_const + { using type = _Tp; }; + + template + struct remove_const<_Tp const> + { using type = _Tp; }; + + /// remove_volatile + template + struct remove_volatile + { using type = _Tp; }; + + template + struct remove_volatile<_Tp volatile> + { using type = _Tp; }; + + /// remove_cv +#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cv) + template + struct remove_cv + { using type = __remove_cv(_Tp); }; +#else + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; +#endif + + /// add_const + template + struct add_const + { using type = _Tp const; }; + + /// add_volatile + template + struct add_volatile + { using type = _Tp volatile; }; + + /// add_cv + template + struct add_cv + { using type = _Tp const volatile; }; + +#ifdef __cpp_lib_transformation_trait_aliases // C++ >= 14 + /// Alias template for remove_const + template + using remove_const_t = typename remove_const<_Tp>::type; + + /// Alias template for remove_volatile + template + using remove_volatile_t = typename remove_volatile<_Tp>::type; + + /// Alias template for remove_cv + template + using remove_cv_t = typename remove_cv<_Tp>::type; + + /// Alias template for add_const + template + using add_const_t = typename add_const<_Tp>::type; + + /// Alias template for add_volatile + template + using add_volatile_t = typename add_volatile<_Tp>::type; + + /// Alias template for add_cv + template + using add_cv_t = typename add_cv<_Tp>::type; +#endif + + // Reference transformations. + + /// remove_reference +#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_reference) + template + struct remove_reference + { using type = __remove_reference(_Tp); }; +#else + template + struct remove_reference + { using type = _Tp; }; + + template + struct remove_reference<_Tp&> + { using type = _Tp; }; + + template + struct remove_reference<_Tp&&> + { using type = _Tp; }; +#endif + + /// add_lvalue_reference + template + struct add_lvalue_reference + { using type = __add_lval_ref_t<_Tp>; }; + + /// add_rvalue_reference + template + struct add_rvalue_reference + { using type = __add_rval_ref_t<_Tp>; }; + +#if __cplusplus > 201103L + /// Alias template for remove_reference + template + using remove_reference_t = typename remove_reference<_Tp>::type; + + /// Alias template for add_lvalue_reference + template + using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; + + /// Alias template for add_rvalue_reference + template + using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; +#endif + + // Sign modifications. + + /// @cond undocumented + + // Utility for constructing identically cv-qualified types. + template + struct __cv_selector; + + template + struct __cv_selector<_Unqualified, false, false> + { using __type = _Unqualified; }; + + template + struct __cv_selector<_Unqualified, false, true> + { using __type = volatile _Unqualified; }; + + template + struct __cv_selector<_Unqualified, true, false> + { using __type = const _Unqualified; }; + + template + struct __cv_selector<_Unqualified, true, true> + { using __type = const volatile _Unqualified; }; + + template::value, + bool _IsVol = is_volatile<_Qualified>::value> + class __match_cv_qualifiers + { + using __match = __cv_selector<_Unqualified, _IsConst, _IsVol>; + + public: + using __type = typename __match::__type; + }; + + // Utility for finding the unsigned versions of signed integral types. + template + struct __make_unsigned + { using __type = _Tp; }; + + template<> + struct __make_unsigned + { using __type = unsigned char; }; + + template<> + struct __make_unsigned + { using __type = unsigned char; }; + + template<> + struct __make_unsigned + { using __type = unsigned short; }; + + template<> + struct __make_unsigned + { using __type = unsigned int; }; + + template<> + struct __make_unsigned + { using __type = unsigned long; }; + + template<> + struct __make_unsigned + { using __type = unsigned long long; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + __extension__ + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0> + { using __type = unsigned __GLIBCXX_TYPE_INT_N_0; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + __extension__ + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1> + { using __type = unsigned __GLIBCXX_TYPE_INT_N_1; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + __extension__ + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2> + { using __type = unsigned __GLIBCXX_TYPE_INT_N_2; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + __extension__ + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3> + { using __type = unsigned __GLIBCXX_TYPE_INT_N_3; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = __is_enum(_Tp)> + class __make_unsigned_selector; + + template + class __make_unsigned_selector<_Tp, true, false> + { + using __unsigned_type + = typename __make_unsigned<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + class __make_unsigned_selector_base + { + protected: + template struct _List { }; + + template + struct _List<_Tp, _Up...> : _List<_Up...> + { static constexpr size_t __size = sizeof(_Tp); }; + + template + struct __select; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, true> + { using __type = _Uint; }; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, false> + : __select<_Sz, _List<_UInts...>> + { }; + }; + + // Choose unsigned integer type with the smallest rank and same size as _Tp + template + class __make_unsigned_selector<_Tp, false, true> + : __make_unsigned_selector_base + { + // With -fshort-enums, an enum may be as small as a char. + using _UInts = _List; + + using __unsigned_type = typename __select::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + // wchar_t, char8_t, char16_t and char32_t are integral types but are + // neither signed integer types nor unsigned integer types, so must be + // transformed to the unsigned integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + /// @endcond + + // Given an integral/enum type, return the corresponding unsigned + // integer type. + // Primary template. + /// make_unsigned + template + struct make_unsigned + { using type = typename __make_unsigned_selector<_Tp>::__type; }; + + // Integral, but don't define. + template<> struct make_unsigned; + template<> struct make_unsigned; + template<> struct make_unsigned; + template<> struct make_unsigned; + + /// @cond undocumented + + // Utility for finding the signed versions of unsigned integral types. + template + struct __make_signed + { using __type = _Tp; }; + + template<> + struct __make_signed + { using __type = signed char; }; + + template<> + struct __make_signed + { using __type = signed char; }; + + template<> + struct __make_signed + { using __type = signed short; }; + + template<> + struct __make_signed + { using __type = signed int; }; + + template<> + struct __make_signed + { using __type = signed long; }; + + template<> + struct __make_signed + { using __type = signed long long; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + __extension__ + template<> + struct __make_signed + { using __type = __GLIBCXX_TYPE_INT_N_0; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + __extension__ + template<> + struct __make_signed + { using __type = __GLIBCXX_TYPE_INT_N_1; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + __extension__ + template<> + struct __make_signed + { using __type = __GLIBCXX_TYPE_INT_N_2; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + __extension__ + template<> + struct __make_signed + { using __type = __GLIBCXX_TYPE_INT_N_3; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = __is_enum(_Tp)> + class __make_signed_selector; + + template + class __make_signed_selector<_Tp, true, false> + { + using __signed_type + = typename __make_signed<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; + }; + + // Choose signed integer type with the smallest rank and same size as _Tp + template + class __make_signed_selector<_Tp, false, true> + { + using __unsigned_type = typename __make_unsigned_selector<_Tp>::__type; + + public: + using __type = typename __make_signed_selector<__unsigned_type>::__type; + }; + + // wchar_t, char16_t and char32_t are integral types but are neither + // signed integer types nor unsigned integer types, so must be + // transformed to the signed integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + +#if defined(_GLIBCXX_USE_CHAR8_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + /// @endcond + + // Given an integral/enum type, return the corresponding signed + // integer type. + // Primary template. + /// make_signed + template + struct make_signed + { using type = typename __make_signed_selector<_Tp>::__type; }; + + // Integral, but don't define. + template<> struct make_signed; + template<> struct make_signed; + template<> struct make_signed; + template<> struct make_signed; + +#if __cplusplus > 201103L + /// Alias template for make_signed + template + using make_signed_t = typename make_signed<_Tp>::type; + + /// Alias template for make_unsigned + template + using make_unsigned_t = typename make_unsigned<_Tp>::type; +#endif + + // Array modifications. + + /// remove_extent + template + struct remove_extent + { using type = _Tp; }; + + template + struct remove_extent<_Tp[_Size]> + { using type = _Tp; }; + + template + struct remove_extent<_Tp[]> + { using type = _Tp; }; + + /// remove_all_extents + template + struct remove_all_extents + { using type = _Tp; }; + + template + struct remove_all_extents<_Tp[_Size]> + { using type = typename remove_all_extents<_Tp>::type; }; + + template + struct remove_all_extents<_Tp[]> + { using type = typename remove_all_extents<_Tp>::type; }; + +#if __cplusplus > 201103L + /// Alias template for remove_extent + template + using remove_extent_t = typename remove_extent<_Tp>::type; + + /// Alias template for remove_all_extents + template + using remove_all_extents_t = typename remove_all_extents<_Tp>::type; +#endif + + // Pointer modifications. + + /// remove_pointer +#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_pointer) + template + struct remove_pointer + { using type = __remove_pointer(_Tp); }; +#else + template + struct __remove_pointer_helper + { using type = _Tp; }; + + template + struct __remove_pointer_helper<_Tp, _Up*> + { using type = _Up; }; + + template + struct remove_pointer + : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> + { }; +#endif + + template + struct __add_pointer_helper + { using type = _Tp; }; + + template + struct __add_pointer_helper<_Tp, __void_t<_Tp*>> + { using type = _Tp*; }; + + /// add_pointer + template + struct add_pointer + : public __add_pointer_helper<_Tp> + { }; + + template + struct add_pointer<_Tp&> + { using type = _Tp*; }; + + template + struct add_pointer<_Tp&&> + { using type = _Tp*; }; + +#if __cplusplus > 201103L + /// Alias template for remove_pointer + template + using remove_pointer_t = typename remove_pointer<_Tp>::type; + + /// Alias template for add_pointer + template + using add_pointer_t = typename add_pointer<_Tp>::type; +#endif + + template + struct __aligned_storage_msa + { + union __type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__)) { } __align; + }; + }; + + /** + * @brief Alignment type. + * + * The value of _Align is a default-alignment which shall be the + * most stringent alignment requirement for any C++ object type + * whose size is no greater than _Len (3.9). The member typedef + * type shall be a POD type suitable for use as uninitialized + * storage for any object whose size is at most _Len and whose + * alignment is a divisor of _Align. + * + * @deprecated Deprecated in C++23. Uses can be replaced by an + * array std::byte[_Len] declared with alignas(_Align). + */ + template::__type)> + struct + _GLIBCXX23_DEPRECATED + aligned_storage + { + union type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__((_Align)))) { } __align; + }; + }; + + template + struct __strictest_alignment + { + static const size_t _S_alignment = 0; + static const size_t _S_size = 0; + }; + + template + struct __strictest_alignment<_Tp, _Types...> + { + static const size_t _S_alignment = + alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment + ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment; + static const size_t _S_size = + sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size + ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size; + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + /** + * @brief Provide aligned storage for types. + * + * [meta.trans.other] + * + * Provides aligned storage for any of the provided types of at + * least size _Len. + * + * @see aligned_storage + * + * @deprecated Deprecated in C++23. + */ + template + struct + _GLIBCXX23_DEPRECATED + aligned_union + { + private: + static_assert(sizeof...(_Types) != 0, "At least one type is required"); + + using __strictest = __strictest_alignment<_Types...>; + static const size_t _S_len = _Len > __strictest::_S_size + ? _Len : __strictest::_S_size; + public: + /// The value of the strictest alignment of _Types. + static const size_t alignment_value = __strictest::_S_alignment; + /// The storage. + using type = typename aligned_storage<_S_len, alignment_value>::type; + }; + + template + const size_t aligned_union<_Len, _Types...>::alignment_value; +#pragma GCC diagnostic pop + + /// @cond undocumented + + // Decay trait for arrays and functions, used for perfect forwarding + // in make_pair, make_tuple, etc. + template + struct __decay_selector + : __conditional_t::value, // false for functions + remove_cv<_Up>, // N.B. DR 705. + add_pointer<_Up>> // function decays to pointer + { }; + + template + struct __decay_selector<_Up[_Nm]> + { using type = _Up*; }; + + template + struct __decay_selector<_Up[]> + { using type = _Up*; }; + + /// @endcond + + /// decay + template + struct decay + { using type = typename __decay_selector<_Tp>::type; }; + + template + struct decay<_Tp&> + { using type = typename __decay_selector<_Tp>::type; }; + + template + struct decay<_Tp&&> + { using type = typename __decay_selector<_Tp>::type; }; + + /// @cond undocumented + + // Helper which adds a reference to a type when given a reference_wrapper + template + struct __strip_reference_wrapper + { + using __type = _Tp; + }; + + template + struct __strip_reference_wrapper > + { + using __type = _Tp&; + }; + + // __decay_t (std::decay_t for C++11). + template + using __decay_t = typename decay<_Tp>::type; + + template + using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; + /// @endcond + + /// @cond undocumented + + // Helper for SFINAE constraints + template + using _Require = __enable_if_t<__and_<_Cond...>::value>; + + // __remove_cvref_t (std::remove_cvref_t for C++11). + template + using __remove_cvref_t + = typename remove_cv::type>::type; + /// @endcond + + // Primary template. + /// Define a member typedef @c type to one of two argument types. + template + struct conditional + { using type = _Iftrue; }; + + // Partial specialization for false. + template + struct conditional + { using type = _Iffalse; }; + + /// common_type + template + struct common_type; + + // Sfinae-friendly common_type implementation: + + /// @cond undocumented + + // For several sfinae-friendly trait implementations we transport both the + // result information (as the member type) and the failure information (no + // member type). This is very similar to std::enable_if, but we cannot use + // that, because we need to derive from them as an implementation detail. + + template + struct __success_type + { using type = _Tp; }; + + struct __failure_type + { }; + + struct __do_common_type_impl + { + template + using __cond_t + = decltype(true ? std::declval<_Tp>() : std::declval<_Up>()); + + // if decay_t() : declval())> + // denotes a valid type, let C denote that type. + template + static __success_type<__decay_t<__cond_t<_Tp, _Up>>> + _S_test(int); + +#if __cplusplus > 201703L + // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, + // let C denote the type decay_t. + template + static __success_type<__remove_cvref_t<__cond_t>> + _S_test_2(int); +#endif + + template + static __failure_type + _S_test_2(...); + + template + static decltype(_S_test_2<_Tp, _Up>(0)) + _S_test(...); + }; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_type<> + { }; + + // If sizeof...(T) is one, the same type, if any, as common_type_t. + template + struct common_type<_Tp0> + : public common_type<_Tp0, _Tp0> + { }; + + // If sizeof...(T) is two, ... + template, typename _Dp2 = __decay_t<_Tp2>> + struct __common_type_impl + { + // If is_same_v is false or is_same_v is false, + // let C denote the same type, if any, as common_type_t. + using type = common_type<_Dp1, _Dp2>; + }; + + template + struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2> + : private __do_common_type_impl + { + // Otherwise, if decay_t() : declval())> + // denotes a valid type, let C denote that type. + using type = decltype(_S_test<_Tp1, _Tp2>(0)); + }; + + // If sizeof...(T) is two, ... + template + struct common_type<_Tp1, _Tp2> + : public __common_type_impl<_Tp1, _Tp2>::type + { }; + + template + struct __common_type_pack + { }; + + template + struct __common_type_fold; + + // If sizeof...(T) is greater than two, ... + template + struct common_type<_Tp1, _Tp2, _Rp...> + : public __common_type_fold, + __common_type_pack<_Rp...>> + { }; + + // Let C denote the same type, if any, as common_type_t. + // If there is such a type C, type shall denote the same type, if any, + // as common_type_t. + template + struct __common_type_fold<_CTp, __common_type_pack<_Rp...>, + __void_t> + : public common_type + { }; + + // Otherwise, there shall be no member type. + template + struct __common_type_fold<_CTp, _Rp, void> + { }; + + template + struct __underlying_type_impl + { + using type = __underlying_type(_Tp); + }; + + template + struct __underlying_type_impl<_Tp, false> + { }; + /// @endcond + + /// The underlying type of an enum. + template + struct underlying_type + : public __underlying_type_impl<_Tp> + { }; + + /// @cond undocumented + template + struct __declval_protector + { + static const bool __stop = false; + }; + /// @endcond + + /** Utility to simplify expressions used in unevaluated operands + * @since C++11 + * @ingroup utilities + */ + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)) + { + static_assert(__declval_protector<_Tp>::__stop, + "declval() must not be used!"); + return __declval<_Tp>(0); + } + + /// result_of + template + struct result_of; + + // Sfinae-friendly result_of implementation: + + /// @cond undocumented + struct __invoke_memfun_ref { }; + struct __invoke_memfun_deref { }; + struct __invoke_memobj_ref { }; + struct __invoke_memobj_deref { }; + struct __invoke_other { }; + + // Associate a tag type with a specialization of __success_type. + template + struct __result_of_success : __success_type<_Tp> + { using __invoke_type = _Tag; }; + + // [func.require] paragraph 1 bullet 1: + struct __result_of_memfun_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_ref + : private __result_of_memfun_ref_impl + { + using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0)); + }; + + // [func.require] paragraph 1 bullet 2: + struct __result_of_memfun_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_deref + : private __result_of_memfun_deref_impl + { + using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0)); + }; + + // [func.require] paragraph 1 bullet 3: + struct __result_of_memobj_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>() + ), __invoke_memobj_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_ref + : private __result_of_memobj_ref_impl + { + using type = decltype(_S_test<_MemPtr, _Arg>(0)); + }; + + // [func.require] paragraph 1 bullet 4: + struct __result_of_memobj_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>() + ), __invoke_memobj_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_deref + : private __result_of_memobj_deref_impl + { + using type = decltype(_S_test<_MemPtr, _Arg>(0)); + }; + + template + struct __result_of_memobj; + + template + struct __result_of_memobj<_Res _Class::*, _Arg> + { + using _Argval = __remove_cvref_t<_Arg>; + using _MemPtr = _Res _Class::*; + using type = typename __conditional_t<__or_, + is_base_of<_Class, _Argval>>::value, + __result_of_memobj_ref<_MemPtr, _Arg>, + __result_of_memobj_deref<_MemPtr, _Arg> + >::type; + }; + + template + struct __result_of_memfun; + + template + struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> + { + using _Argval = typename remove_reference<_Arg>::type; + using _MemPtr = _Res _Class::*; + using type = typename __conditional_t::value, + __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, + __result_of_memfun_deref<_MemPtr, _Arg, _Args...> + >::type; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2219. INVOKE-ing a pointer to member with a reference_wrapper + // as the object expression + + // Used by result_of, invoke etc. to unwrap a reference_wrapper. + template> + struct __inv_unwrap + { + using type = _Tp; + }; + + template + struct __inv_unwrap<_Tp, reference_wrapper<_Up>> + { + using type = _Up&; + }; + + template + struct __result_of_impl + { + using type = __failure_type; + }; + + template + struct __result_of_impl + : public __result_of_memobj<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type> + { }; + + template + struct __result_of_impl + : public __result_of_memfun<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type, _Args...> + { }; + + // [func.require] paragraph 1 bullet 5: + struct __result_of_other_impl + { + template + static __result_of_success()(std::declval<_Args>()...) + ), __invoke_other> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_impl + : private __result_of_other_impl + { + using type = decltype(_S_test<_Functor, _ArgTypes...>(0)); + }; + + // __invoke_result (std::invoke_result for C++11) + template + struct __invoke_result + : public __result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type + >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type + >::value, + _Functor, _ArgTypes... + >::type + { }; + + // __invoke_result_t (std::invoke_result_t for C++11) + template + using __invoke_result_t = typename __invoke_result<_Fn, _Args...>::type; + /// @endcond + + template + struct result_of<_Functor(_ArgTypes...)> + : public __invoke_result<_Functor, _ArgTypes...> + { } _GLIBCXX17_DEPRECATED_SUGGEST("std::invoke_result"); + +#if __cplusplus >= 201402L +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// Alias template for aligned_storage + template::__type)> + using aligned_storage_t _GLIBCXX23_DEPRECATED = typename aligned_storage<_Len, _Align>::type; + + template + using aligned_union_t _GLIBCXX23_DEPRECATED = typename aligned_union<_Len, _Types...>::type; +#pragma GCC diagnostic pop + + /// Alias template for decay + template + using decay_t = typename decay<_Tp>::type; + + /// Alias template for enable_if + template + using enable_if_t = typename enable_if<_Cond, _Tp>::type; + + /// Alias template for conditional + template + using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type; + + /// Alias template for common_type + template + using common_type_t = typename common_type<_Tp...>::type; + + /// Alias template for underlying_type + template + using underlying_type_t = typename underlying_type<_Tp>::type; + + /// Alias template for result_of + template + using result_of_t = typename result_of<_Tp>::type; +#endif // C++14 + +#ifdef __cpp_lib_void_t // C++ >= 17 || GNU++ >= 11 + /// A metafunction that always yields void, used for detecting valid types. + template using void_t = void; +#endif + + /// @cond undocumented + + // Detection idiom. + // Detect whether _Op<_Args...> is a valid type, use default _Def if not. + +#if __cpp_concepts + // Implementation of the detection idiom (negative case). + template class _Op, typename... _Args> + struct __detected_or + { + using type = _Def; + using __is_detected = false_type; + }; + + // Implementation of the detection idiom (positive case). + template class _Op, typename... _Args> + requires requires { typename _Op<_Args...>; } + struct __detected_or<_Def, _Op, _Args...> + { + using type = _Op<_Args...>; + using __is_detected = true_type; + }; +#else + /// Implementation of the detection idiom (negative case). + template class _Op, typename... _Args> + struct __detector + { + using type = _Default; + using __is_detected = false_type; + }; + + /// Implementation of the detection idiom (positive case). + template class _Op, + typename... _Args> + struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> + { + using type = _Op<_Args...>; + using __is_detected = true_type; + }; + + template class _Op, + typename... _Args> + using __detected_or = __detector<_Default, void, _Op, _Args...>; +#endif // __cpp_concepts + + // _Op<_Args...> if that is a valid type, otherwise _Default. + template class _Op, + typename... _Args> + using __detected_or_t + = typename __detected_or<_Default, _Op, _Args...>::type; + + /** + * Use SFINAE to determine if the type _Tp has a publicly-accessible + * member type _NTYPE. + */ +#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ + template> \ + struct __has_##_NTYPE \ + : false_type \ + { }; \ + template \ + struct __has_##_NTYPE<_Tp, __void_t> \ + : true_type \ + { }; + + template + struct __is_swappable; + + template + struct __is_nothrow_swappable; + + template + struct __is_tuple_like_impl : false_type + { }; + + // Internal type trait that allows us to sfinae-protect tuple_cat. + template + struct __is_tuple_like + : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type + { }; + /// @endcond + + template + _GLIBCXX20_CONSTEXPR + inline + _Require<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>> + swap(_Tp&, _Tp&) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>::value); + + template + _GLIBCXX20_CONSTEXPR + inline + __enable_if_t<__is_swappable<_Tp>::value> + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + noexcept(__is_nothrow_swappable<_Tp>::value); + + /// @cond undocumented + namespace __swappable_details { + using std::swap; + + struct __do_is_swappable_impl + { + template(), std::declval<_Tp&>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_details + + template + struct __is_swappable_impl + : public __swappable_details::__do_is_swappable_impl + { + using type = decltype(__test<_Tp>(0)); + }; + + template + struct __is_nothrow_swappable_impl + : public __swappable_details::__do_is_nothrow_swappable_impl + { + using type = decltype(__test<_Tp>(0)); + }; + + template + struct __is_swappable + : public __is_swappable_impl<_Tp>::type + { }; + + template + struct __is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { }; + /// @endcond + +#ifdef __cpp_lib_is_swappable // C++ >= 17 || GNU++ >= 11 + /// Metafunctions used for detecting swappable types: p0185r1 + + /// is_swappable + template + struct is_swappable + : public __is_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_swappable + template + struct is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __cplusplus >= 201402L + /// is_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_v = + is_swappable<_Tp>::value; + + /// is_nothrow_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v = + is_nothrow_swappable<_Tp>::value; +#endif // __cplusplus >= 201402L + + /// @cond undocumented + namespace __swappable_with_details { + using std::swap; + + struct __do_is_swappable_with_impl + { + template(), std::declval<_Up>())), + typename + = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_with_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) + && + noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_with_details + + template + struct __is_swappable_with_impl + : public __swappable_with_details::__do_is_swappable_with_impl + { + using type = decltype(__test<_Tp, _Up>(0)); + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_swappable_impl + { + using type = decltype(__test<_Tp&>(0)); + }; + + template + struct __is_nothrow_swappable_with_impl + : public __swappable_with_details::__do_is_nothrow_swappable_with_impl + { + using type = decltype(__test<_Tp, _Up>(0)); + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_nothrow_swappable_impl + { + using type = decltype(__test<_Tp&>(0)); + }; + /// @endcond + + /// is_swappable_with + template + struct is_swappable_with + : public __is_swappable_with_impl<_Tp, _Up>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "first template argument must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "second template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_swappable_with + template + struct is_nothrow_swappable_with + : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "first template argument must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "second template argument must be a complete class or an unbounded array"); + }; + +#if __cplusplus >= 201402L + /// is_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_with_v = + is_swappable_with<_Tp, _Up>::value; + + /// is_nothrow_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v = + is_nothrow_swappable_with<_Tp, _Up>::value; +#endif // __cplusplus >= 201402L + +#endif // __cpp_lib_is_swappable + + /// @cond undocumented + + // __is_invocable (std::is_invocable for C++11) + + // The primary template is used for invalid INVOKE expressions. + template::value, typename = void> + struct __is_invocable_impl + : false_type + { + using __nothrow_conv = false_type; // For is_nothrow_invocable_r + }; + + // Used for valid INVOKE and INVOKE expressions. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ true, + __void_t> + : true_type + { + using __nothrow_conv = true_type; // For is_nothrow_invocable_r + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + // Used for INVOKE expressions to check the implicit conversion to R. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ false, + __void_t> + { + private: + // The type of the INVOKE expression. + using _Res_t = typename _Result::type; + + // Unlike declval, this doesn't add_rvalue_reference, so it respects + // guaranteed copy elision. + static _Res_t _S_get() noexcept; + + // Used to check if _Res_t can implicitly convert to _Tp. + template + static void _S_conv(__type_identity_t<_Tp>) noexcept; + + // This overload is viable if INVOKE(f, args...) can convert to _Tp. + template(_S_get())), + typename = decltype(_S_conv<_Tp>(_S_get())), +#if __has_builtin(__reference_converts_from_temporary) + bool _Dangle = __reference_converts_from_temporary(_Tp, _Res_t) +#else + bool _Dangle = false +#endif + > + static __bool_constant<_Nothrow && !_Dangle> + _S_test(int); + + template + static false_type + _S_test(...); + + public: + // For is_invocable_r + using type = decltype(_S_test<_Ret, /* Nothrow = */ true>(1)); + + // For is_nothrow_invocable_r + using __nothrow_conv = decltype(_S_test<_Ret>(1)); + }; +#pragma GCC diagnostic pop + + template + struct __is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { }; + + template + constexpr bool __call_is_nt(__invoke_memfun_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept((std::declval<_Up>().*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memfun_deref) + { + return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept(std::declval<_Up>().*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_deref) + { + return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_other) + { + return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); + } + + template + struct __call_is_nothrow + : __bool_constant< + std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) + > + { }; + + template + using __call_is_nothrow_ + = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; + + // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) + template + struct __is_nothrow_invocable + : __and_<__is_invocable<_Fn, _Args...>, + __call_is_nothrow_<_Fn, _Args...>>::type + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + struct __nonesuchbase {}; + struct __nonesuch : private __nonesuchbase { + ~__nonesuch() = delete; + __nonesuch(__nonesuch const&) = delete; + void operator=(__nonesuch const&) = delete; + }; +#pragma GCC diagnostic pop + /// @endcond + +#ifdef __cpp_lib_is_invocable // C++ >= 17 + /// std::invoke_result + template + struct invoke_result + : public __invoke_result<_Functor, _ArgTypes...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}), + "_Functor must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + }; + + /// std::invoke_result_t + template + using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; + + /// std::is_invocable + template + struct is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + }; + + /// std::is_invocable_r + template + struct is_invocable_r + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), + "_Ret must be a complete class or an unbounded array"); + }; + + /// std::is_nothrow_invocable + template + struct is_nothrow_invocable + : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + // This checks that the INVOKE expression is well-formed and that the + // conversion to R does not throw. It does *not* check whether the INVOKE + // expression itself can throw. That is done by __call_is_nothrow_ instead. + template + using __is_nt_invocable_impl + = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv; + /// @endcond + + /// std::is_nothrow_invocable_r + template + struct is_nothrow_invocable_r + : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), + "_Ret must be a complete class or an unbounded array"); + }; +#endif // __cpp_lib_is_invocable + +#if __cpp_lib_type_trait_variable_templates // C++ >= 17 + /** + * @defgroup variable_templates Variable templates for type traits + * @ingroup metaprogramming + * + * Each variable `is_xxx_v` is a boolean constant with the same value + * as the `value` member of the corresponding type trait `is_xxx`. + * + * @since C++17 unless noted otherwise. + */ + + /** + * @{ + * @ingroup variable_templates + */ +template + inline constexpr bool is_void_v = is_void<_Tp>::value; +template + inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; +template + inline constexpr bool is_integral_v = is_integral<_Tp>::value; +template + inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array) +template + inline constexpr bool is_array_v = __is_array(_Tp); +#else +template + inline constexpr bool is_array_v = false; +template + inline constexpr bool is_array_v<_Tp[]> = true; +template + inline constexpr bool is_array_v<_Tp[_Num]> = true; +#endif + +template + inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; +template + inline constexpr bool is_lvalue_reference_v = false; +template + inline constexpr bool is_lvalue_reference_v<_Tp&> = true; +template + inline constexpr bool is_rvalue_reference_v = false; +template + inline constexpr bool is_rvalue_reference_v<_Tp&&> = true; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer) +template + inline constexpr bool is_member_object_pointer_v = + __is_member_object_pointer(_Tp); +#else +template + inline constexpr bool is_member_object_pointer_v = + is_member_object_pointer<_Tp>::value; +#endif + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer) +template + inline constexpr bool is_member_function_pointer_v = + __is_member_function_pointer(_Tp); +#else +template + inline constexpr bool is_member_function_pointer_v = + is_member_function_pointer<_Tp>::value; +#endif + +template + inline constexpr bool is_enum_v = __is_enum(_Tp); +template + inline constexpr bool is_union_v = __is_union(_Tp); +template + inline constexpr bool is_class_v = __is_class(_Tp); +// is_function_v is defined below, after is_const_v. + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference) +template + inline constexpr bool is_reference_v = __is_reference(_Tp); +#else +template + inline constexpr bool is_reference_v = false; +template + inline constexpr bool is_reference_v<_Tp&> = true; +template + inline constexpr bool is_reference_v<_Tp&&> = true; +#endif + +template + inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; +template + inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object) +template + inline constexpr bool is_object_v = __is_object(_Tp); +#else +template + inline constexpr bool is_object_v = is_object<_Tp>::value; +#endif + +template + inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; +template + inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer) +template + inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp); +#else +template + inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; +#endif + +template + inline constexpr bool is_const_v = false; +template + inline constexpr bool is_const_v = true; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) +template + inline constexpr bool is_function_v = __is_function(_Tp); +#else +template + inline constexpr bool is_function_v = !is_const_v; +template + inline constexpr bool is_function_v<_Tp&> = false; +template + inline constexpr bool is_function_v<_Tp&&> = false; +#endif + +template + inline constexpr bool is_volatile_v = false; +template + inline constexpr bool is_volatile_v = true; + +template + inline constexpr bool is_trivial_v = __is_trivial(_Tp); +template + inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp); +template + inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp); +template + _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout_v && is_trivial_v") + inline constexpr bool is_pod_v = __is_pod(_Tp); +template + _GLIBCXX17_DEPRECATED + inline constexpr bool is_literal_type_v = __is_literal_type(_Tp); +template + inline constexpr bool is_empty_v = __is_empty(_Tp); +template + inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); +template + inline constexpr bool is_abstract_v = __is_abstract(_Tp); +template + inline constexpr bool is_final_v = __is_final(_Tp); + +template + inline constexpr bool is_signed_v = is_signed<_Tp>::value; +template + inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; + +template + inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); +template + inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); +template + inline constexpr bool is_copy_constructible_v + = __is_constructible(_Tp, __add_lval_ref_t); +template + inline constexpr bool is_move_constructible_v + = __is_constructible(_Tp, __add_rval_ref_t<_Tp>); + +template + inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up); +template + inline constexpr bool is_copy_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t); +template + inline constexpr bool is_move_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + +template + inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; + +template + inline constexpr bool is_trivially_constructible_v + = __is_trivially_constructible(_Tp, _Args...); +template + inline constexpr bool is_trivially_default_constructible_v + = __is_trivially_constructible(_Tp); +template + inline constexpr bool is_trivially_copy_constructible_v + = __is_trivially_constructible(_Tp, __add_lval_ref_t); +template + inline constexpr bool is_trivially_move_constructible_v + = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>); + +template + inline constexpr bool is_trivially_assignable_v + = __is_trivially_assignable(_Tp, _Up); +template + inline constexpr bool is_trivially_copy_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t); +template + inline constexpr bool is_trivially_move_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>); + +#if __cpp_concepts +template + inline constexpr bool is_trivially_destructible_v = false; + +template + requires (!is_reference_v<_Tp>) && requires (_Tp& __t) { __t.~_Tp(); } + inline constexpr bool is_trivially_destructible_v<_Tp> + = __has_trivial_destructor(_Tp); +template + inline constexpr bool is_trivially_destructible_v<_Tp&> = true; +template + inline constexpr bool is_trivially_destructible_v<_Tp&&> = true; +template + inline constexpr bool is_trivially_destructible_v<_Tp[_Nm]> + = is_trivially_destructible_v<_Tp>; +#else +template + inline constexpr bool is_trivially_destructible_v = + is_trivially_destructible<_Tp>::value; +#endif + +template + inline constexpr bool is_nothrow_constructible_v + = __is_nothrow_constructible(_Tp, _Args...); +template + inline constexpr bool is_nothrow_default_constructible_v + = __is_nothrow_constructible(_Tp); +template + inline constexpr bool is_nothrow_copy_constructible_v + = __is_nothrow_constructible(_Tp, __add_lval_ref_t); +template + inline constexpr bool is_nothrow_move_constructible_v + = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>); + +template + inline constexpr bool is_nothrow_assignable_v + = __is_nothrow_assignable(_Tp, _Up); +template + inline constexpr bool is_nothrow_copy_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t); +template + inline constexpr bool is_nothrow_move_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + +template + inline constexpr bool is_nothrow_destructible_v = + is_nothrow_destructible<_Tp>::value; + +template + inline constexpr bool has_virtual_destructor_v + = __has_virtual_destructor(_Tp); + +template + inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; + +template + inline constexpr size_t rank_v = 0; +template + inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>; +template + inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>; + +template + inline constexpr size_t extent_v = 0; +template + inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size; +template + inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>; +template + inline constexpr size_t extent_v<_Tp[], 0> = 0; +template + inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>; + +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same) +template + inline constexpr bool is_same_v = __is_same(_Tp, _Up); +#else +template + inline constexpr bool is_same_v = false; +template + inline constexpr bool is_same_v<_Tp, _Tp> = true; +#endif +template + inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived); +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible) +template + inline constexpr bool is_convertible_v = __is_convertible(_From, _To); +#else +template + inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; +#endif +template + inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; +template + inline constexpr bool is_nothrow_invocable_v + = is_nothrow_invocable<_Fn, _Args...>::value; +template + inline constexpr bool is_invocable_r_v + = is_invocable_r<_Ret, _Fn, _Args...>::value; +template + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; +/// @} +#endif // __cpp_lib_type_trait_variable_templates + +#ifdef __cpp_lib_has_unique_object_representations // C++ >= 17 && HAS_UNIQ_OBJ_REP + /// has_unique_object_representations + /// @since C++17 + template + struct has_unique_object_representations + : bool_constant<__has_unique_object_representations( + remove_cv_t> + )> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +# if __cpp_lib_type_trait_variable_templates // C++ >= 17 + /// @ingroup variable_templates + template + inline constexpr bool has_unique_object_representations_v + = has_unique_object_representations<_Tp>::value; +# endif +#endif + +#ifdef __cpp_lib_is_aggregate // C++ >= 17 && builtin_is_aggregate + /// is_aggregate - true if the type is an aggregate. + /// @since C++17 + template + struct is_aggregate + : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> + { }; + +# if __cpp_lib_type_trait_variable_templates // C++ >= 17 + /** is_aggregate_v - true if the type is an aggregate. + * @ingroup variable_templates + * @since C++17 + */ + template + inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>); +# endif +#endif + + /** * Remove references and cv-qualifiers. + * @since C++20 + * @{ + */ +#ifdef __cpp_lib_remove_cvref // C++ >= 20 +# if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cvref) + template + struct remove_cvref + { using type = __remove_cvref(_Tp); }; +# else + template + struct remove_cvref + { using type = typename remove_cv<_Tp>::type; }; + + template + struct remove_cvref<_Tp&> + { using type = typename remove_cv<_Tp>::type; }; + + template + struct remove_cvref<_Tp&&> + { using type = typename remove_cv<_Tp>::type; }; +# endif + + template + using remove_cvref_t = typename remove_cvref<_Tp>::type; + /// @} +#endif // __cpp_lib_remove_cvref + +#ifdef __cpp_lib_type_identity // C++ >= 20 + /** * Identity metafunction. + * @since C++20 + * @{ + */ + template + struct type_identity { using type = _Tp; }; + + template + using type_identity_t = typename type_identity<_Tp>::type; + /// @} +#endif + +#ifdef __cpp_lib_unwrap_ref // C++ >= 20 + /** Unwrap a reference_wrapper + * @since C++20 + * @{ + */ + template + struct unwrap_reference { using type = _Tp; }; + + template + struct unwrap_reference> { using type = _Tp&; }; + + template + using unwrap_reference_t = typename unwrap_reference<_Tp>::type; + /// @} + + /** Decay type and if it's a reference_wrapper, unwrap it + * @since C++20 + * @{ + */ + template + struct unwrap_ref_decay { using type = unwrap_reference_t>; }; + + template + using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; + /// @} +#endif // __cpp_lib_unwrap_ref + +#ifdef __cpp_lib_bounded_array_traits // C++ >= 20 + /// True for a type that is an array of known bound. + /// @ingroup variable_templates + /// @since C++20 +# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_bounded_array) + template + inline constexpr bool is_bounded_array_v = __is_bounded_array(_Tp); +# else + template + inline constexpr bool is_bounded_array_v = false; + + template + inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true; +# endif + + /// True for a type that is an array of unknown bound. + /// @ingroup variable_templates + /// @since C++20 + template + inline constexpr bool is_unbounded_array_v = false; + + template + inline constexpr bool is_unbounded_array_v<_Tp[]> = true; + + /// True for a type that is an array of known bound. + /// @since C++20 + template + struct is_bounded_array + : public bool_constant> + { }; + + /// True for a type that is an array of unknown bound. + /// @since C++20 + template + struct is_unbounded_array + : public bool_constant> + { }; +#endif // __cpp_lib_bounded_array_traits + +#if __has_builtin(__is_layout_compatible) && __cplusplus >= 202002L + + /// @since C++20 + template + struct is_layout_compatible + : bool_constant<__is_layout_compatible(_Tp, _Up)> + { }; + + /// @ingroup variable_templates + /// @since C++20 + template + constexpr bool is_layout_compatible_v + = __is_layout_compatible(_Tp, _Up); + +#if __has_builtin(__builtin_is_corresponding_member) +# ifndef __cpp_lib_is_layout_compatible +# error "libstdc++ bug: is_corresponding_member and is_layout_compatible are provided but their FTM is not set" +# endif + + /// @since C++20 + template + constexpr bool + is_corresponding_member(_M1 _S1::*__m1, _M2 _S2::*__m2) noexcept + { return __builtin_is_corresponding_member(__m1, __m2); } +#endif +#endif + +#if __has_builtin(__is_pointer_interconvertible_base_of) \ + && __cplusplus >= 202002L + /// True if `_Derived` is standard-layout and has a base class of type `_Base` + /// @since C++20 + template + struct is_pointer_interconvertible_base_of + : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)> + { }; + + /// @ingroup variable_templates + /// @since C++20 + template + constexpr bool is_pointer_interconvertible_base_of_v + = __is_pointer_interconvertible_base_of(_Base, _Derived); + +#if __has_builtin(__builtin_is_pointer_interconvertible_with_class) +# ifndef __cpp_lib_is_pointer_interconvertible +# error "libstdc++ bug: is_pointer_interconvertible available but FTM is not set" +# endif + + /// True if `__mp` points to the first member of a standard-layout type + /// @returns true if `s.*__mp` is pointer-interconvertible with `s` + /// @since C++20 + template + constexpr bool + is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept + { return __builtin_is_pointer_interconvertible_with_class(__mp); } +#endif +#endif + +#ifdef __cpp_lib_is_scoped_enum // C++ >= 23 + /// True if the type is a scoped enumeration type. + /// @since C++23 + +# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum) + template + struct is_scoped_enum + : bool_constant<__is_scoped_enum(_Tp)> + { }; +# else + template + struct is_scoped_enum + : false_type + { }; + + template + requires __is_enum(_Tp) + && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete + struct is_scoped_enum<_Tp> + : bool_constant + { }; +# endif + + /// @ingroup variable_templates + /// @since C++23 +# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum) + template + inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp); +# else + template + inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value; +# endif +#endif + +#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp + /// True if _Tp is a reference type, a _Up value can be bound to _Tp in + /// direct-initialization, and a temporary object would be bound to + /// the reference, false otherwise. + /// @since C++23 + template + struct reference_constructs_from_temporary + : public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}) + && std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// True if _Tp is a reference type, a _Up value can be bound to _Tp in + /// copy-initialization, and a temporary object would be bound to + /// the reference, false otherwise. + /// @since C++23 + template + struct reference_converts_from_temporary + : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}) + && std::__is_complete_or_unbounded(__type_identity<_Up>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// @ingroup variable_templates + /// @since C++23 + template + inline constexpr bool reference_constructs_from_temporary_v + = reference_constructs_from_temporary<_Tp, _Up>::value; + + /// @ingroup variable_templates + /// @since C++23 + template + inline constexpr bool reference_converts_from_temporary_v + = reference_converts_from_temporary<_Tp, _Up>::value; +#endif // __cpp_lib_reference_from_temporary + +#ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL + /// Returns true only when called during constant evaluation. + /// @since C++20 + constexpr inline bool + is_constant_evaluated() noexcept + { +#if __cpp_if_consteval >= 202106L + if consteval { return true; } else { return false; } +#else + return __builtin_is_constant_evaluated(); +#endif + } +#endif + +#if __cplusplus >= 202002L + /// @cond undocumented + template + using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type; + + template + using __cond_res + = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); + + template + struct __common_ref_impl + { }; + + // [meta.trans.other], COMMON-REF(A, B) + template + using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type; + + // COND-RES(COPYCV(X, Y) &, COPYCV(Y, X) &) + template + using __condres_cvref + = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>; + + // If A and B are both lvalue reference types, ... + template + struct __common_ref_impl<_Xp&, _Yp&, __void_t<__condres_cvref<_Xp, _Yp>>> + : enable_if>, + __condres_cvref<_Xp, _Yp>> + { }; + + // let C be remove_reference_t&& + template + using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&; + + // If A and B are both rvalue reference types, ... + template + struct __common_ref_impl<_Xp&&, _Yp&&, + _Require>, + is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>> + { using type = __common_ref_C<_Xp, _Yp>; }; + + // let D be COMMON-REF(const X&, Y&) + template + using __common_ref_D = __common_ref; + + // If A is an rvalue reference and B is an lvalue reference, ... + template + struct __common_ref_impl<_Xp&&, _Yp&, + _Require>>> + { using type = __common_ref_D<_Xp, _Yp>; }; + + // If A is an lvalue reference and B is an rvalue reference, ... + template + struct __common_ref_impl<_Xp&, _Yp&&> + : __common_ref_impl<_Yp&&, _Xp&> + { }; + /// @endcond + + template class _TQual, template class _UQual> + struct basic_common_reference + { }; + + /// @cond undocumented + template + struct __xref + { template using __type = __copy_cv<_Tp, _Up>; }; + + template + struct __xref<_Tp&> + { template using __type = __copy_cv<_Tp, _Up>&; }; + + template + struct __xref<_Tp&&> + { template using __type = __copy_cv<_Tp, _Up>&&; }; + + template + using __basic_common_ref + = typename basic_common_reference, + remove_cvref_t<_Tp2>, + __xref<_Tp1>::template __type, + __xref<_Tp2>::template __type>::type; + /// @endcond + + template + struct common_reference; + + template + using common_reference_t = typename common_reference<_Tp...>::type; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_reference<> + { }; + + // If sizeof...(T) is one ... + template + struct common_reference<_Tp0> + { using type = _Tp0; }; + + /// @cond undocumented + template + struct __common_reference_impl + : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> + { }; + + // If sizeof...(T) is two ... + template + struct common_reference<_Tp1, _Tp2> + : __common_reference_impl<_Tp1, _Tp2> + { }; + + // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1&, _Tp2&, 1, + void_t<__common_ref<_Tp1&, _Tp2&>>> + { using type = __common_ref<_Tp1&, _Tp2&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&&>>> + { using type = __common_ref<_Tp1&&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&, _Tp2&&>>> + { using type = __common_ref<_Tp1&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&>>> + { using type = __common_ref<_Tp1&&, _Tp2&>; }; + + // Otherwise, if basic_common_reference<...>::type is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 2, + void_t<__basic_common_ref<_Tp1, _Tp2>>> + { using type = __basic_common_ref<_Tp1, _Tp2>; }; + + // Otherwise, if COND-RES(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 3, + void_t<__cond_res<_Tp1, _Tp2>>> + { using type = __cond_res<_Tp1, _Tp2>; }; + + // Otherwise, if common_type_t is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 4, + void_t>> + { using type = common_type_t<_Tp1, _Tp2>; }; + + // Otherwise, there shall be no member type. + template + struct __common_reference_impl<_Tp1, _Tp2, 5, void> + { }; + + // Otherwise, if sizeof...(T) is greater than two, ... + template + struct common_reference<_Tp1, _Tp2, _Rest...> + : __common_type_fold, + __common_type_pack<_Rest...>> + { }; + + // Reuse __common_type_fold for common_reference + template + struct __common_type_fold, + __common_type_pack<_Rest...>, + void_t>> + : public common_reference, _Rest...> + { }; + /// @endcond + +#endif // C++2a + + /// @} group metaprogramming + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TYPE_TRAITS diff --git a/template/sysroot/include/typeindex b/template/sysroot/include/typeindex new file mode 100644 index 0000000..894b133 --- /dev/null +++ b/template/sysroot/include/typeindex @@ -0,0 +1,129 @@ +// C++11 -*- C++ -*- + +// Copyright (C) 2010-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/typeindex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPEINDEX +#define _GLIBCXX_TYPEINDEX 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Class type_index + * @ingroup utilities + * + * The class type_index provides a simple wrapper for type_info + * which can be used as an index type in associative containers + * (23.6) and in unordered associative containers (23.7). + */ + struct type_index + { + type_index(const type_info& __rhs) noexcept + : _M_target(&__rhs) { } + + bool + operator==(const type_index& __rhs) const noexcept + { return *_M_target == *__rhs._M_target; } + +#if ! __cpp_lib_three_way_comparison + bool + operator!=(const type_index& __rhs) const noexcept + { return *_M_target != *__rhs._M_target; } +#endif + + bool + operator<(const type_index& __rhs) const noexcept + { return _M_target->before(*__rhs._M_target); } + + bool + operator<=(const type_index& __rhs) const noexcept + { return !__rhs._M_target->before(*_M_target); } + + bool + operator>(const type_index& __rhs) const noexcept + { return __rhs._M_target->before(*_M_target); } + + bool + operator>=(const type_index& __rhs) const noexcept + { return !_M_target->before(*__rhs._M_target); } + +#if __cpp_lib_three_way_comparison + strong_ordering + operator<=>(const type_index& __rhs) const noexcept + { + if (*_M_target == *__rhs._M_target) + return strong_ordering::equal; + if (_M_target->before(*__rhs._M_target)) + return strong_ordering::less; + return strong_ordering::greater; + } +#endif + + size_t + hash_code() const noexcept + { return _M_target->hash_code(); } + + const char* + name() const noexcept + { return _M_target->name(); } + + private: + const type_info* _M_target; + }; + + template struct hash; + + /// std::hash specialization for type_index. + template<> + struct hash + { + typedef size_t result_type; + typedef type_index argument_type; + + size_t + operator()(const type_index& __ti) const noexcept + { return __ti.hash_code(); } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TYPEINDEX diff --git a/template/sysroot/include/typeinfo b/template/sysroot/include/typeinfo new file mode 100644 index 0000000..fcc3077 --- /dev/null +++ b/template/sysroot/include/typeinfo @@ -0,0 +1,254 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994-2024 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file typeinfo + * This is a Standard C++ Library header. + */ + +#ifndef _TYPEINFO +#define _TYPEINFO + +#pragma GCC system_header + +#include +#if __cplusplus >= 201103L +#include +#endif + +#define __glibcxx_want_constexpr_typeinfo +#include + +#pragma GCC visibility push(default) + +extern "C++" { + +namespace __cxxabiv1 +{ + class __class_type_info; +} // namespace __cxxabiv1 + +// Determine whether typeinfo names for the same type are merged (in which +// case comparison can just compare pointers) or not (in which case strings +// must be compared), and whether comparison is to be implemented inline or +// not. We used to do inline pointer comparison by default if weak symbols +// are available, but even with weak symbols sometimes names are not merged +// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by +// default. For ABI compatibility, we do the strcmp inline if weak symbols +// are available, and out-of-line if not. Out-of-line pointer comparison +// is used where the object files are to be portable to multiple systems, +// some of which may not be able to use pointer comparison, but the +// particular system for which libstdc++ is being built can use pointer +// comparison; in particular for most ARM EABI systems, where the ABI +// specifies out-of-line comparison. The compiler's target configuration +// can override the defaults by defining __GXX_TYPEINFO_EQUALITY_INLINE to +// 1 or 0 to indicate whether or not comparison is inline, and +// __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to indicate whether or not pointer +// comparison can be used. + +#ifndef __GXX_MERGED_TYPEINFO_NAMES +// By default, typeinfo names are not merged. +#define __GXX_MERGED_TYPEINFO_NAMES 0 +#endif + +// By default follow the old inline rules to avoid ABI changes. +#ifndef __GXX_TYPEINFO_EQUALITY_INLINE +# if !__GXX_WEAK__ +# define __GXX_TYPEINFO_EQUALITY_INLINE 0 +# else +# define __GXX_TYPEINFO_EQUALITY_INLINE 1 +# endif +#endif + +namespace std +{ + /** + * @brief Part of RTTI. + * + * The @c type_info class describes type information generated by + * an implementation. + */ + class type_info + { + public: + /** Destructor first. Being the first non-inline virtual function, this + * controls in which translation unit the vtable is emitted. The + * compiler makes use of that information to know where to emit + * the runtime-mandated type_info structures in the new-abi. */ + virtual ~type_info(); + + /** Returns an @e implementation-defined byte string; this is not + * portable between compilers! */ + const char* name() const _GLIBCXX_NOEXCEPT + { return __name[0] == '*' ? __name + 1 : __name; } + + /** Returns true if `*this` precedes `__arg` in the implementation's + * collation order. */ + bool before(const type_info& __arg) const _GLIBCXX_NOEXCEPT; + + _GLIBCXX23_CONSTEXPR + bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT; + +#if __cpp_impl_three_way_comparison < 201907L + bool operator!=(const type_info& __arg) const _GLIBCXX_NOEXCEPT + { return !operator==(__arg); } +#endif + +#if __cplusplus >= 201103L + size_t hash_code() const noexcept + { +# if !__GXX_MERGED_TYPEINFO_NAMES + return _Hash_bytes(name(), __builtin_strlen(name()), + static_cast(0xc70f6907UL)); +# else + return reinterpret_cast(__name); +# endif + } +#endif // C++11 + + // Return true if this is a pointer type of some kind + virtual bool __is_pointer_p() const; + + // Return true if this is a function type + virtual bool __is_function_p() const; + + // Try and catch a thrown type. Store an adjusted pointer to the + // caught type in THR_OBJ. If THR_TYPE is not a pointer type, then + // THR_OBJ points to the thrown object. If THR_TYPE is a pointer + // type, then THR_OBJ is the pointer itself. OUTER indicates the + // number of outer pointers, and whether they were const + // qualified. + virtual bool __do_catch(const type_info *__thr_type, void **__thr_obj, + unsigned __outer) const; + + // Internally used during catch matching + virtual bool __do_upcast(const __cxxabiv1::__class_type_info *__target, + void **__obj_ptr) const; + + protected: + const char *__name; + + explicit type_info(const char *__n): __name(__n) { } + + private: + // type_info objects cannot be copied. +#if __cplusplus >= 201103L + type_info& operator=(const type_info&) = delete; + type_info(const type_info&) = delete; +#else + type_info& operator=(const type_info&); + type_info(const type_info&); +#endif + +#if ! __GXX_TYPEINFO_EQUALITY_INLINE + bool __equal(const type_info&) const _GLIBCXX_NOEXCEPT; +#endif + }; + +#if __GXX_TYPEINFO_EQUALITY_INLINE + inline bool + type_info::before(const type_info& __arg) const _GLIBCXX_NOEXCEPT + { +#if !__GXX_MERGED_TYPEINFO_NAMES + // Even with the new abi, on systems that support dlopen + // we can run into cases where type_info names aren't merged, + // so we still need to do string comparison. + if (__name[0] != '*' || __arg.__name[0] != '*') + return __builtin_strcmp (__name, __arg.__name) < 0; +#else + // On some targets we can rely on type_info's NTBS being unique, + // and therefore address comparisons are sufficient. +#endif + + // In old abi, or when weak symbols are not supported, there can + // be multiple instances of a type_info object for one + // type. Uniqueness must use the __name value, not object address. + return __name < __arg.__name; + } +#endif + +#if __GXX_TYPEINFO_EQUALITY_INLINE || __cplusplus > 202002L + _GLIBCXX23_CONSTEXPR inline bool + type_info::operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT + { + if (std::__is_constant_evaluated()) + return this == &__arg; + + if (__name == __arg.__name) + return true; + +#if !__GXX_TYPEINFO_EQUALITY_INLINE + // ABI requires comparisons to be non-inline. + return __equal(__arg); +#elif !__GXX_MERGED_TYPEINFO_NAMES + // Need to do string comparison. + return __name[0] != '*' && __builtin_strcmp (__name, __arg.name()) == 0; +#else + return false; +#endif + } +# endif + + + /** + * @brief Thrown during incorrect typecasting. + * @ingroup exceptions + * + * If you attempt an invalid @c dynamic_cast expression, an instance of + * this class (or something derived from this class) is thrown. */ + class bad_cast : public exception + { + public: + bad_cast() _GLIBCXX_USE_NOEXCEPT { } + + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_cast() _GLIBCXX_USE_NOEXCEPT; + + // See comment in eh_exception.cc. + virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; + }; + + /** + * @brief Thrown when a NULL pointer in a @c typeid expression is used. + * @ingroup exceptions + */ + class bad_typeid : public exception + { + public: + bad_typeid () _GLIBCXX_USE_NOEXCEPT { } + + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_typeid() _GLIBCXX_USE_NOEXCEPT; + + // See comment in eh_exception.cc. + virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; + }; +} // namespace std + +} // extern "C++" + +#pragma GCC visibility pop + +#endif diff --git a/template/sysroot/include/uintrintrin.h b/template/sysroot/include/uintrintrin.h new file mode 100644 index 0000000..a77c305 --- /dev/null +++ b/template/sysroot/include/uintrintrin.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _UINTRNTRIN_H_INCLUDED +#define _UINTRNTRIN_H_INCLUDED + +#ifdef __x86_64__ + +#ifndef __UINTR__ +#pragma GCC push_options +#pragma GCC target ("uintr") +#define __DISABLE_UINTR__ +#endif /* __UINTR__ */ + +struct __uintr_frame +{ + /* RIP of the interrupted user process. */ + unsigned long long rip; + /* RFLAGS of the interrupted user process. */ + unsigned long long rflags; + /* RSP of the interrupted user process. */ + unsigned long long rsp; +}; + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_clui (void) +{ + __builtin_ia32_clui (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_stui (void) +{ + __builtin_ia32_stui (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_senduipi (unsigned long long __R) +{ + __builtin_ia32_senduipi (__R); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_testui (void) +{ + return __builtin_ia32_testui (); +} + +#ifdef __DISABLE_UINTR__ +#undef __DISABLE_UINTR__ +#pragma GCC pop_options +#endif /* __DISABLE_UINTR__ */ + +#endif + +#endif /* _UINTRNTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/unwind.h b/template/sysroot/include/unwind.h new file mode 100644 index 0000000..d6e4284 --- /dev/null +++ b/template/sysroot/include/unwind.h @@ -0,0 +1,298 @@ +/* Exception handling and frame unwind runtime interface routines. + Copyright (C) 2001-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* This is derived from the C++ ABI for IA-64. Where we diverge + for cross-architecture compatibility are noted with "@@@". */ + +#ifndef _UNWIND_H +#define _UNWIND_H + +#if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__) +/* Only for _GCC_specific_handler. */ +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifndef HIDE_EXPORTS +#pragma GCC visibility push(default) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Level 1: Base ABI */ + +/* @@@ The IA-64 ABI uses uint64 throughout. Most places this is + inefficient for 32-bit and smaller machines. */ +typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__))); +#if defined(__ia64__) && defined(__hpux__) +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__))); +#else +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +#endif +typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + +/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and + consumer of an exception. We'll go along with this for now even on + 32-bit machines. We'll need to provide some other option for + 16-bit machines and for machines with > 8 bits per byte. */ +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); + +/* The unwind interface uses reason codes in several contexts to + identify the reasons for failures or other actions. */ +typedef enum +{ + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + + +/* The unwind interface uses a pointer to an exception header object + as its representation of an exception being thrown. In general, the + full representation of an exception object is language- and + implementation-specific, but it will be prefixed by a header + understood by the unwind interface. */ + +struct _Unwind_Exception; + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +struct _Unwind_Exception +{ + _Unwind_Exception_Class exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + +#if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__) + _Unwind_Word private_[6]; +#else + _Unwind_Word private_1; + _Unwind_Word private_2; +#endif + + /* @@@ The IA-64 ABI says that this structure must be double-word aligned. + Taking that literally does not make much sense generically. Instead we + provide the maximum alignment required by any type for the machine. */ +} __attribute__((__aligned__)); + + +/* The ACTIONS argument to the personality routine is a bitwise OR of one + or more of the following constants. */ +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 + +/* The target can override this macro to define any back-end-specific + attributes required for the lowest-level stack frame. */ +#ifndef LIBGCC2_UNWIND_ATTRIBUTE +#define LIBGCC2_UNWIND_ATTRIBUTE +#endif + +/* This is an opaque type used to refer to a system-specific data + structure used by the system unwinder. This context is created and + destroyed by the system, and passed to the personality routine + during unwinding. */ +struct _Unwind_Context; + +/* Raise an exception, passing along the given exception object. */ +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_RaiseException (struct _Unwind_Exception *); + +/* Raise an exception for forced unwinding. */ + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_ForcedUnwind (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); + +/* Helper to invoke the exception_cleanup routine. */ +extern void _Unwind_DeleteException (struct _Unwind_Exception *); + +/* Resume propagation of an existing exception. This is used after + e.g. executing cleanup code, and not to implement rethrowing. */ +extern void LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_Resume (struct _Unwind_Exception *); + +/* @@@ Resume propagation of a FORCE_UNWIND exception, or to rethrow + a normal exception that was handled. */ +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); + +/* @@@ Use unwind data to perform a stack backtrace. The trace callback + is called for every stack frame in the call chain, but no cleanup + actions are performed. */ +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +/* These functions are used for communicating information about the unwind + context (i.e. the unwind descriptors and the user register state) between + the unwind library and the personality routine and landing pad. Only + selected registers may be manipulated. */ + +extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + +extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); +extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *); +extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); + +/* @@@ Retrieve the CFA of the given context. */ +extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + +extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *); + +extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *); + + +/* The personality routine is the function in the C++ (or other language) + runtime library which serves as an interface between the system unwind + library and language-specific exception handling semantics. It is + specific to the code fragment described by an unwind info block, and + it is always referenced via the pointer in the unwind info block, and + hence it has no ABI-specified name. + + Note that this implies that two different C++ implementations can + use different names, and have different contents in the language + specific data area. Moreover, that the language specific data + area contains no version info because name of the function invoked + provides more effective versioning by detecting at link time the + lack of code to handle the different data format. */ + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + +/* @@@ The following alternate entry points are for setjmp/longjmp + based unwinding. */ + +struct SjLj_Function_Context; +extern void _Unwind_SjLj_Register (struct SjLj_Function_Context *); +extern void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); + +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_SjLj_RaiseException (struct _Unwind_Exception *); +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_SjLj_ForcedUnwind (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +extern void LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_SjLj_Resume (struct _Unwind_Exception *); +extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE +_Unwind_SjLj_Resume_or_Rethrow (struct _Unwind_Exception *); + +/* @@@ The following provide access to the base addresses for text + and data-relative addressing in the LDSA. In order to stay link + compatible with the standard ABI for IA-64, we inline these. */ + +#ifdef __ia64__ +static inline _Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *_C) +{ + /* The GP is stored in R1. */ + return _Unwind_GetGR (_C, 1); +} + +static inline _Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *_C __attribute__ ((__unused__))) +{ + __builtin_abort (); + return 0; +} + +/* @@@ Retrieve the Backing Store Pointer of the given context. */ +extern _Unwind_Word _Unwind_GetBSP (struct _Unwind_Context *); +#else +extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *); +extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *); +#endif + +/* @@@ Given an address, return the entry point of the function that + contains it. */ +extern void * _Unwind_FindEnclosingFunction (void *pc); + +#ifndef __SIZEOF_LONG__ + #error "__SIZEOF_LONG__ macro not defined" +#endif + +#ifndef __SIZEOF_POINTER__ + #error "__SIZEOF_POINTER__ macro not defined" +#endif + + +/* leb128 type numbers have a potentially unlimited size. + The target of the following definitions of _sleb128_t and _uleb128_t + is to have efficient data types large enough to hold the leb128 type + numbers used in the unwind code. + Mostly these types will simply be defined to long and unsigned long + except when a unsigned long data type on the target machine is not + capable of storing a pointer. */ + +#if __SIZEOF_LONG__ >= __SIZEOF_POINTER__ + typedef long _sleb128_t; + typedef unsigned long _uleb128_t; +#elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__ + typedef long long _sleb128_t; + typedef unsigned long long _uleb128_t; +#else +# error "What type shall we use for _sleb128_t?" +#endif + +#if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__) +/* Handles the mapping from SEH to GCC interfaces. */ +EXCEPTION_DISPOSITION _GCC_specific_handler (PEXCEPTION_RECORD, void *, + PCONTEXT, PDISPATCHER_CONTEXT, + _Unwind_Personality_Fn); +#endif + +#ifdef __cplusplus +} +#endif + +#ifndef HIDE_EXPORTS +#pragma GCC visibility pop +#endif + +/* Additional actions to unwind number of stack frames. */ +#define _Unwind_Frames_Extra(frames) + +/* Increment frame count. */ +#define _Unwind_Frames_Increment(exc, context, frames) frames++ + +#endif /* unwind.h */ diff --git a/template/sysroot/include/usermsrintrin.h b/template/sysroot/include/usermsrintrin.h new file mode 100644 index 0000000..9b6f6d2 --- /dev/null +++ b/template/sysroot/include/usermsrintrin.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2022-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#if !defined _X86GPRINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _USER_MSRINTRIN_H_INCLUDED +#define _USER_MSRINTRIN_H_INCLUDED + +#ifdef __x86_64__ + +#ifndef __USER_MSR__ +#pragma GCC push_options +#pragma GCC target("usermsr") +#define __DISABLE_USER_MSR__ +#endif /* __USER_MSR__ */ + +extern __inline unsigned long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_urdmsr (unsigned long long __A) +{ + return (unsigned long long) __builtin_ia32_urdmsr (__A); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_uwrmsr (unsigned long long __A, unsigned long long __B) +{ + __builtin_ia32_uwrmsr (__A, __B); +} + +#ifdef __DISABLE_USER_MSR__ +#undef __DISABLE_USER_MSR__ +#pragma GCC pop_options +#endif /* __DISABLE_USER_MSR__ */ + +#endif /* __x86_64__ */ + +#endif /* _USER_MSRINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/utility b/template/sysroot/include/utility new file mode 100644 index 0000000..212513f --- /dev/null +++ b/template/sysroot/include/utility @@ -0,0 +1,235 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/utility + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UTILITY +#define _GLIBCXX_UTILITY 1 + +#pragma GCC system_header + +/** + * @defgroup utilities Utilities + * + * Basic function and class templates used with the rest of the library. + * Includes pair, swap, forward/move helpers, declval, integer_sequence. + */ + +#include +#include +#include + +#if __cplusplus >= 201103L + +#include +#include +#include +#include + +#if __cplusplus >= 202002L +#include // __is_standard_integer, __int_traits +#endif + +#define __glibcxx_want_addressof_constexpr +#define __glibcxx_want_as_const +#define __glibcxx_want_constexpr_algorithms +#define __glibcxx_want_constexpr_utility +#define __glibcxx_want_exchange_function +#define __glibcxx_want_forward_like +#define __glibcxx_want_integer_comparison_functions +#define __glibcxx_want_integer_sequence +#define __glibcxx_want_ranges_zip +#define __glibcxx_want_to_underlying +#define __glibcxx_want_tuple_element_t +#define __glibcxx_want_tuples_by_type +#define __glibcxx_want_unreachable +#define __glibcxx_want_tuple_like +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __cpp_lib_exchange_function // C++ >= 14 + /// Assign @p __new_val to @p __obj and return its previous value. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + exchange(_Tp& __obj, _Up&& __new_val) + noexcept(__and_, + is_nothrow_assignable<_Tp&, _Up>>::value) + { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } +#endif + +#ifdef __cpp_lib_as_const // C++ >= 17 + template + [[nodiscard]] + constexpr add_const_t<_Tp>& + as_const(_Tp& __t) noexcept + { return __t; } + + template + void as_const(const _Tp&&) = delete; +#endif + +#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20 + template + constexpr bool + cmp_equal(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t == __u; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; + else + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_not_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_equal(__t, __u); } + + template + constexpr bool + cmp_less(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t < __u; + else if constexpr (is_signed_v<_Tp>) + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; + else + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_greater(_Tp __t, _Up __u) noexcept + { return std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_less_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_greater_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__t, __u); } + + template + constexpr bool + in_range(_Tp __t) noexcept + { + static_assert(__is_standard_integer<_Res>::value); + static_assert(__is_standard_integer<_Tp>::value); + using __gnu_cxx::__int_traits; + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) + return __int_traits<_Res>::__min <= __t + && __t <= __int_traits<_Res>::__max; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; + else + return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); + } +#endif // __cpp_lib_integer_comparison_functions + +#ifdef __cpp_lib_to_underlying // C++ >= 23 + /// Convert an object of enumeration type to its underlying type. + template + [[nodiscard]] + constexpr underlying_type_t<_Tp> + to_underlying(_Tp __value) noexcept + { return static_cast>(__value); } +#endif + +#ifdef __cpp_lib_unreachable // C++ >= 23 + /// Informs the compiler that program control flow never reaches this point. + /** + * Evaluating a call to this function results in undefined behaviour. + * This can be used as an assertion informing the compiler that certain + * conditions are impossible, for when the compiler is unable to determine + * that by itself. + * + * For example, it can be used to prevent warnings about reaching the + * end of a non-void function without returning. + * + * @since C++23 + */ + [[noreturn,__gnu__::__always_inline__]] + inline void + unreachable() + { +#ifdef _GLIBCXX_DEBUG + std::__glibcxx_assert_fail(nullptr, 0, "std::unreachable()", nullptr); +#elif defined _GLIBCXX_ASSERTIONS + __builtin_trap(); +#else + __builtin_unreachable(); +#endif + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + +#endif /* _GLIBCXX_UTILITY */ diff --git a/template/sysroot/include/vaesintrin.h b/template/sysroot/include/vaesintrin.h new file mode 100644 index 0000000..d47ed2d --- /dev/null +++ b/template/sysroot/include/vaesintrin.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2017-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef __VAESINTRIN_H_INCLUDED +#define __VAESINTRIN_H_INCLUDED + +#if !defined(__VAES__) +#pragma GCC push_options +#pragma GCC target("vaes") +#define __DISABLE_VAES__ +#endif /* __VAES__ */ + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_aesdec_epi128 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_vaesdec_v32qi ((__v32qi) __A, (__v32qi) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_aesdeclast_epi128 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_vaesdeclast_v32qi ((__v32qi) __A, + (__v32qi) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_aesenc_epi128 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_vaesenc_v32qi ((__v32qi) __A, (__v32qi) __B); +} + +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_aesenclast_epi128 (__m256i __A, __m256i __B) +{ + return (__m256i)__builtin_ia32_vaesenclast_v32qi ((__v32qi) __A, + (__v32qi) __B); +} + +#ifdef __DISABLE_VAES__ +#undef __DISABLE_VAES__ +#pragma GCC pop_options +#endif /* __DISABLE_VAES__ */ + + +#if !defined(__VAES__) || !defined(__AVX512F__) || !defined(__EVEX512__) +#pragma GCC push_options +#pragma GCC target("vaes,avx512f,evex512") +#define __DISABLE_VAESF__ +#endif /* __VAES__ */ + + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_aesdec_epi128 (__m512i __A, __m512i __B) +{ + return (__m512i)__builtin_ia32_vaesdec_v64qi ((__v64qi) __A, (__v64qi) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_aesdeclast_epi128 (__m512i __A, __m512i __B) +{ + return (__m512i)__builtin_ia32_vaesdeclast_v64qi ((__v64qi) __A, + (__v64qi) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_aesenc_epi128 (__m512i __A, __m512i __B) +{ + return (__m512i)__builtin_ia32_vaesenc_v64qi ((__v64qi) __A, (__v64qi) __B); +} + +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_aesenclast_epi128 (__m512i __A, __m512i __B) +{ + return (__m512i)__builtin_ia32_vaesenclast_v64qi ((__v64qi) __A, + (__v64qi) __B); +} + +#ifdef __DISABLE_VAESF__ +#undef __DISABLE_VAESF__ +#pragma GCC pop_options +#endif /* __DISABLE_VAES__ */ + +#endif /* __VAESINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/varargs.h b/template/sysroot/include/varargs.h new file mode 100644 index 0000000..4b9803e --- /dev/null +++ b/template/sysroot/include/varargs.h @@ -0,0 +1,7 @@ +#ifndef _VARARGS_H +#define _VARARGS_H + +#error "GCC no longer implements ." +#error "Revise your code to use ." + +#endif diff --git a/template/sysroot/include/variant b/template/sysroot/include/variant new file mode 100644 index 0000000..748e9ba --- /dev/null +++ b/template/sysroot/include/variant @@ -0,0 +1,1970 @@ +// -*- C++ -*- + +// Copyright (C) 2016-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file variant + * This is the `` C++ Library header. + */ + +#ifndef _GLIBCXX_VARIANT +#define _GLIBCXX_VARIANT 1 + +#pragma GCC system_header + +#define __glibcxx_want_freestanding_variant +#define __glibcxx_want_variant +#include + +#ifdef __cpp_lib_variant // C++ >= 17 +#include +#include +#include +#include +#include +#include +#include // _Select_int +#include +#include +#include // in_place_index_t +#if __cplusplus >= 202002L +# include +#endif + +// C++ < 20 || __cpp_concepts < 202002L || __cpp_constexpr < 201811L +#if __cpp_lib_variant < 202106L +# include // Use __aligned_membuf instead of union. +#endif + + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template class tuple; + template class variant; + template struct hash; + + template + struct variant_size; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size> + : std::integral_constant {}; + + template + inline constexpr size_t variant_size_v = variant_size<_Variant>::value; + + template + inline constexpr size_t + variant_size_v> = sizeof...(_Types); + + template + inline constexpr size_t + variant_size_v> = sizeof...(_Types); + + template + struct variant_alternative; + + template + struct variant_alternative<_Np, variant<_Types...>> + { + static_assert(_Np < sizeof...(_Types)); + + using type = typename _Nth_type<_Np, _Types...>::type; + }; + + template + using variant_alternative_t = + typename variant_alternative<_Np, _Variant>::type; + + template + struct variant_alternative<_Np, const _Variant> + { using type = const variant_alternative_t<_Np, _Variant>; }; + + template + struct variant_alternative<_Np, volatile _Variant> + { using type = volatile variant_alternative_t<_Np, _Variant>; }; + + template + struct variant_alternative<_Np, const volatile _Variant> + { using type = const volatile variant_alternative_t<_Np, _Variant>; }; + + inline constexpr size_t variant_npos = -1; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const& + get(const variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const&& + get(const variant<_Types...>&&); + + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants); + + template + _GLIBCXX20_CONSTEXPR + decltype(auto) + __variant_cast(_Tp&& __rhs) + { + if constexpr (is_lvalue_reference_v<_Tp>) + { + if constexpr (is_const_v>) + return static_cast&>(__rhs); + else + return static_cast&>(__rhs); + } + else + return static_cast&&>(__rhs); + } + +namespace __detail +{ +namespace __variant +{ + // used for raw visitation + struct __variant_cookie {}; + // used for raw visitation with indices passed in + struct __variant_idx_cookie { using type = __variant_idx_cookie; }; + // Used to enable deduction (and same-type checking) for std::visit: + template struct __deduce_visit_result { using type = _Tp; }; + + // Visit variants that might be valueless. + template + constexpr void + __raw_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // Visit variants that might be valueless, passing indices to the visitor. + template + constexpr void + __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // The __as function templates implement the exposition-only "as-variant" + + template + constexpr std::variant<_Types...>& + __as(std::variant<_Types...>& __v) noexcept + { return __v; } + + template + constexpr const std::variant<_Types...>& + __as(const std::variant<_Types...>& __v) noexcept + { return __v; } + + template + constexpr std::variant<_Types...>&& + __as(std::variant<_Types...>&& __v) noexcept + { return std::move(__v); } + + template + constexpr const std::variant<_Types...>&& + __as(const std::variant<_Types...>&& __v) noexcept + { return std::move(__v); } + + // For C++17: + // _Uninitialized is guaranteed to be a trivially destructible type, + // even if T is not. + // For C++20: + // _Uninitialized is trivially destructible iff T is, so _Variant_union + // needs a constrained non-trivial destructor. + template> + struct _Uninitialized; + + template + struct _Uninitialized<_Type, true> + { + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + : _M_storage(std::forward<_Args>(__args)...) + { } + + constexpr const _Type& _M_get() const & noexcept + { return _M_storage; } + + constexpr _Type& _M_get() & noexcept + { return _M_storage; } + + constexpr const _Type&& _M_get() const && noexcept + { return std::move(_M_storage); } + + constexpr _Type&& _M_get() && noexcept + { return std::move(_M_storage); } + + _Type _M_storage; + }; + + template + struct _Uninitialized<_Type, false> + { +#if __cpp_lib_variant >= 202106L + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + : _M_storage(std::forward<_Args>(__args)...) + { } + + constexpr ~_Uninitialized() { } + + _Uninitialized(const _Uninitialized&) = default; + _Uninitialized(_Uninitialized&&) = default; + _Uninitialized& operator=(const _Uninitialized&) = default; + _Uninitialized& operator=(_Uninitialized&&) = default; + + constexpr const _Type& _M_get() const & noexcept + { return _M_storage; } + + constexpr _Type& _M_get() & noexcept + { return _M_storage; } + + constexpr const _Type&& _M_get() const && noexcept + { return std::move(_M_storage); } + + constexpr _Type&& _M_get() && noexcept + { return std::move(_M_storage); } + + struct _Empty_byte { }; + + union { + _Empty_byte _M_empty; + _Type _M_storage; + }; +#else + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + { + ::new ((void*)std::addressof(_M_storage)) + _Type(std::forward<_Args>(__args)...); + } + + const _Type& _M_get() const & noexcept + { return *_M_storage._M_ptr(); } + + _Type& _M_get() & noexcept + { return *_M_storage._M_ptr(); } + + const _Type&& _M_get() const && noexcept + { return std::move(*_M_storage._M_ptr()); } + + _Type&& _M_get() && noexcept + { return std::move(*_M_storage._M_ptr()); } + + __gnu_cxx::__aligned_membuf<_Type> _M_storage; +#endif + }; + + template + constexpr decltype(auto) + __get_n(_Union&& __u) noexcept + { + if constexpr (_Np == 0) + return std::forward<_Union>(__u)._M_first._M_get(); + else if constexpr (_Np == 1) + return std::forward<_Union>(__u)._M_rest._M_first._M_get(); + else if constexpr (_Np == 2) + return std::forward<_Union>(__u)._M_rest._M_rest._M_first._M_get(); + else + return __variant::__get_n<_Np - 3>( + std::forward<_Union>(__u)._M_rest._M_rest._M_rest); + } + + // Returns the typed storage for __v. + template + constexpr decltype(auto) + __get(_Variant&& __v) noexcept + { return __variant::__get_n<_Np>(std::forward<_Variant>(__v)._M_u); } + + // Gets the _Uninitialized to construct into for __u. + template + constexpr decltype(auto) + __construct_n(_Union& __u) noexcept + { + if constexpr (_Np == 0) + return &__u._M_first; + else if constexpr (_Np == 1) + { + std::_Construct(&__u._M_rest); + return &__u._M_rest._M_first; + } + else if constexpr (_Np == 2) + { + std::_Construct(&__u._M_rest); + std::_Construct(&__u._M_rest._M_rest); + return &__u._M_rest._M_rest._M_first; + } + else + { + std::_Construct(&__u._M_rest); + std::_Construct(&__u._M_rest._M_rest); + std::_Construct(&__u._M_rest._M_rest._M_rest); + return __variant::__construct_n<_Np - 3>(__u._M_rest._M_rest._M_rest); + } + } + + template + struct _Traits + { + static constexpr bool _S_default_ctor = + is_default_constructible_v::type>; + static constexpr bool _S_copy_ctor = + (is_copy_constructible_v<_Types> && ...); + static constexpr bool _S_move_ctor = + (is_move_constructible_v<_Types> && ...); + static constexpr bool _S_copy_assign = + _S_copy_ctor + && (is_copy_assignable_v<_Types> && ...); + static constexpr bool _S_move_assign = + _S_move_ctor + && (is_move_assignable_v<_Types> && ...); + + static constexpr bool _S_trivial_dtor = + (is_trivially_destructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_ctor = + (is_trivially_copy_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_move_ctor = + (is_trivially_move_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_assign = + _S_trivial_dtor && _S_trivial_copy_ctor + && (is_trivially_copy_assignable_v<_Types> && ...); + static constexpr bool _S_trivial_move_assign = + _S_trivial_dtor && _S_trivial_move_ctor + && (is_trivially_move_assignable_v<_Types> && ...); + + // The following nothrow traits are for non-trivial SMFs. Trivial SMFs + // are always nothrow. + static constexpr bool _S_nothrow_default_ctor = + is_nothrow_default_constructible_v< + typename _Nth_type<0, _Types...>::type>; + static constexpr bool _S_nothrow_copy_ctor = false; + static constexpr bool _S_nothrow_move_ctor = + (is_nothrow_move_constructible_v<_Types> && ...); + static constexpr bool _S_nothrow_copy_assign = false; + static constexpr bool _S_nothrow_move_assign = + _S_nothrow_move_ctor + && (is_nothrow_move_assignable_v<_Types> && ...); + }; + + // Defines members and ctors. + template + union _Variadic_union + { + _Variadic_union() = default; + + template + _Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete; + }; + + template + union _Variadic_union<__trivially_destructible, _First, _Rest...> + { + constexpr _Variadic_union() : _M_rest() { } + + template + constexpr + _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template + constexpr + _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + +#if __cpp_lib_variant >= 202106L + _Variadic_union(const _Variadic_union&) = default; + _Variadic_union(_Variadic_union&&) = default; + _Variadic_union& operator=(const _Variadic_union&) = default; + _Variadic_union& operator=(_Variadic_union&&) = default; + + ~_Variadic_union() = default; + + constexpr ~_Variadic_union() + requires (!__trivially_destructible) + { } +#endif + + _Uninitialized<_First> _M_first; + _Variadic_union<__trivially_destructible, _Rest...> _M_rest; + }; + + // _Never_valueless_alt is true for variant alternatives that can + // always be placed in a variant without it becoming valueless. + + // For suitably-small, trivially copyable types we can create temporaries + // on the stack and then memcpy them into place. + template + struct _Never_valueless_alt + : __and_, is_trivially_copyable<_Tp>> + { }; + + // Specialize _Never_valueless_alt for other types which have a + // non-throwing and cheap move construction and move assignment operator, + // so that emplacing the type will provide the strong exception-safety + // guarantee, by creating and moving a temporary. + // Whether _Never_valueless_alt is true or not affects the ABI of a + // variant using that alternative, so we can't change the value later! + + // True if every alternative in _Types... can be emplaced in a variant + // without it becoming valueless. If this is true, variant<_Types...> + // can never be valueless, which enables some minor optimizations. + template + constexpr bool __never_valueless() + { + return _Traits<_Types...>::_S_move_assign + && (_Never_valueless_alt<_Types>::value && ...); + } + + // Defines index and the dtor, possibly trivial. + template + struct _Variant_storage; + + template + using __select_index = + typename __select_int::_Select_int_base::type::value_type; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + constexpr void + _M_reset() + { + if (!_M_valid()) [[unlikely]] + return; + + std::__do_visit([](auto&& __this_mem) mutable + { + std::_Destroy(std::__addressof(__this_mem)); + }, __variant_cast<_Types...>(*this)); + + _M_index = static_cast<__index_type>(variant_npos); + } + + _GLIBCXX20_CONSTEXPR + ~_Variant_storage() + { _M_reset(); } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + return this->_M_index != __index_type(variant_npos); + } + + _Variadic_union _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + constexpr void + _M_reset() noexcept + { _M_index = static_cast<__index_type>(variant_npos); } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + // It would be nice if we could just return true for -fno-exceptions. + // It's possible (but inadvisable) that a std::variant could become + // valueless in a translation unit compiled with -fexceptions and then + // be passed to functions compiled with -fno-exceptions. We would need + // some #ifdef _GLIBCXX_NO_EXCEPTIONS_GLOBALLY property to elide all + // checks for valueless_by_exception(). + return this->_M_index != static_cast<__index_type>(variant_npos); + } + + _Variadic_union _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + // Implementation of v.emplace(args...). + template + _GLIBCXX20_CONSTEXPR + inline void + __emplace(_Variant_storage<_Triv, _Types...>& __v, _Args&&... __args) + { + __v._M_reset(); + auto* __addr = __variant::__construct_n<_Np>(__v._M_u); + std::_Construct(__addr, in_place_index<0>, + std::forward<_Args>(__args)...); + // Construction didn't throw, so can set the new index now: + __v._M_index = _Np; + } + + template + using _Variant_storage_alias = + _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; + + // The following are (Copy|Move) (ctor|assign) layers for forwarding + // triviality and handling non-trivial SMF behaviors. + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + + _GLIBCXX20_CONSTEXPR + _Copy_ctor_base(const _Copy_ctor_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + constexpr size_t __j = __rhs_index; + if constexpr (__j != variant_npos) + std::_Construct(std::__addressof(this->_M_u), + in_place_index<__j>, __rhs_mem); + }, __variant_cast<_Types...>(__rhs)); + this->_M_index = __rhs._M_index; + } + + _Copy_ctor_base(_Copy_ctor_base&&) = default; + _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default; + _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default; + }; + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_ctor_alias = + _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + + _GLIBCXX20_CONSTEXPR + _Move_ctor_base(_Move_ctor_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_ctor) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + constexpr size_t __j = __rhs_index; + if constexpr (__j != variant_npos) + std::_Construct(std::__addressof(this->_M_u), + in_place_index<__j>, + std::forward(__rhs_mem)); + }, __variant_cast<_Types...>(std::move(__rhs))); + this->_M_index = __rhs._M_index; + } + + _Move_ctor_base(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(_Move_ctor_base&&) = default; + }; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Move_ctor_alias = + _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + + _GLIBCXX20_CONSTEXPR + _Copy_assign_base& + operator=(const _Copy_assign_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + constexpr size_t __j = __rhs_index; + if constexpr (__j == variant_npos) + this->_M_reset(); // Make *this valueless. + else if (this->_M_index == __j) + __variant::__get<__j>(*this) = __rhs_mem; + else + { + using _Tj = typename _Nth_type<__j, _Types...>::type; + if constexpr (is_nothrow_copy_constructible_v<_Tj> + || !is_nothrow_move_constructible_v<_Tj>) + __variant::__emplace<__j>(*this, __rhs_mem); + else + { + using _Variant = variant<_Types...>; + _Variant& __self = __variant_cast<_Types...>(*this); + __self = _Variant(in_place_index<__j>, __rhs_mem); + } + } + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Copy_assign_base(const _Copy_assign_base&) = default; + _Copy_assign_base(_Copy_assign_base&&) = default; + _Copy_assign_base& operator=(_Copy_assign_base&&) = default; + }; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_assign_alias = + _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + + _GLIBCXX20_CONSTEXPR + _Move_assign_base& + operator=(_Move_assign_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + constexpr size_t __j = __rhs_index; + if constexpr (__j != variant_npos) + { + if (this->_M_index == __j) + __variant::__get<__j>(*this) = std::move(__rhs_mem); + else + { + using _Tj = typename _Nth_type<__j, _Types...>::type; + if constexpr (is_nothrow_move_constructible_v<_Tj>) + __variant::__emplace<__j>(*this, std::move(__rhs_mem)); + else + { + using _Variant = variant<_Types...>; + _Variant& __self = __variant_cast<_Types...>(*this); + __self.template emplace<__j>(std::move(__rhs_mem)); + } + } + } + else + this->_M_reset(); + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Move_assign_base(const _Move_assign_base&) = default; + _Move_assign_base(_Move_assign_base&&) = default; + _Move_assign_base& operator=(const _Move_assign_base&) = default; + }; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Move_assign_alias = + _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>; + + template + struct _Variant_base : _Move_assign_alias<_Types...> + { + using _Base = _Move_assign_alias<_Types...>; + + constexpr + _Variant_base() noexcept(_Traits<_Types...>::_S_nothrow_default_ctor) + : _Variant_base(in_place_index<0>) { } + + template + constexpr explicit + _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) + : _Base(__i, std::forward<_Args>(__args)...) + { } + + _Variant_base(const _Variant_base&) = default; + _Variant_base(_Variant_base&&) = default; + _Variant_base& operator=(const _Variant_base&) = default; + _Variant_base& operator=(_Variant_base&&) = default; + }; + + template + inline constexpr bool __exactly_once + = std::__find_uniq_type_in_pack<_Tp, _Types...>() < sizeof...(_Types); + + // Helper used to check for valid conversions that don't involve narrowing. + template struct _Arr { _Ti _M_x[1]; }; + + // "Build an imaginary function FUN(Ti) for each alternative type Ti" + template + struct _Build_FUN + { + // This function means 'using _Build_FUN::_S_fun;' is valid, + // but only static functions will be considered in the call below. + void _S_fun() = delete; + }; + + // "... for which Ti x[] = {std::forward(t)}; is well-formed." + template + struct _Build_FUN<_Ind, _Tp, _Ti, + void_t{{std::declval<_Tp>()}})>> + { + // This is the FUN function for type _Ti, with index _Ind + static integral_constant _S_fun(_Ti); + }; + + template>> + struct _Build_FUNs; + + template + struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>> + : _Build_FUN<_Ind, _Tp, _Ti>... + { + using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...; + }; + + // The index j of the overload FUN(Tj) selected by overload resolution + // for FUN(std::forward<_Tp>(t)) + template + using _FUN_type + = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>())); + + // The index selected for FUN(std::forward(t)), or variant_npos if none. + template + inline constexpr size_t + __accepted_index = variant_npos; + + template + inline constexpr size_t + __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>> + = _FUN_type<_Tp, _Variant>::value; + + template> + inline constexpr bool + __extra_visit_slot_needed = false; + + template + inline constexpr bool + __extra_visit_slot_needed<__variant_cookie, _Var, variant<_Types...>> + = !__variant::__never_valueless<_Types...>(); + + template + inline constexpr bool + __extra_visit_slot_needed<__variant_idx_cookie, _Var, variant<_Types...>> + = !__variant::__never_valueless<_Types...>(); + + // Used for storing a multi-dimensional vtable. + template + struct _Multi_array; + + // Partial specialization with rank zero, stores a single _Tp element. + template + struct _Multi_array<_Tp> + { + template + struct __untag_result + : false_type + { using element_type = _Tp; }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-qualifiers" + template + struct __untag_result + : false_type + { using element_type = void(*)(_Args...); }; +#pragma GCC diagnostic pop + + template + struct __untag_result<__variant_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__variant_idx_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)> + : true_type + { using element_type = _Res(*)(_Args...); }; + + using __result_is_deduced = __untag_result<_Tp>; + + constexpr const typename __untag_result<_Tp>::element_type& + _M_access() const + { return _M_data; } + + typename __untag_result<_Tp>::element_type _M_data; + }; + + // Partial specialization with rank >= 1. + template + struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...> + { + static constexpr size_t __index = + sizeof...(_Variants) - sizeof...(__rest) - 1; + + using _Variant = typename _Nth_type<__index, _Variants...>::type; + + static constexpr int __do_cookie = + __extra_visit_slot_needed<_Ret, _Variant> ? 1 : 0; + + using _Tp = _Ret(*)(_Visitor, _Variants...); + + template + constexpr decltype(auto) + _M_access(size_t __first_index, _Args... __rest_indices) const + { + return _M_arr[__first_index + __do_cookie] + ._M_access(__rest_indices...); + } + + _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie]; + }; + + // Creates a multi-dimensional vtable recursively. + // + // For example, + // visit([](auto, auto){}, + // variant(), // typedef'ed as V1 + // variant()) // typedef'ed as V2 + // will trigger instantiations of: + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 2>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 2>> + // The returned multi-dimensional vtable can be fast accessed by the visitor + // using index calculation. + template + struct __gen_vtable_impl; + + // Defines the _S_apply() member that returns a _Multi_array populated + // with function pointers that perform the visitation expressions e(m) + // for each valid pack of indexes into the variant types _Variants. + // + // This partial specialization builds up the index sequences by recursively + // calling _S_apply() on the next specialization of __gen_vtable_impl. + // The base case of the recursion defines the actual function pointers. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, + std::index_sequence<__indices...>> + { + using _Next = + remove_reference_t::type>; + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + __dimensions...>; + + static constexpr _Array_type + _S_apply() + { + _Array_type __vtable{}; + _S_apply_all_alts( + __vtable, make_index_sequence>()); + return __vtable; + } + + template + static constexpr void + _S_apply_all_alts(_Array_type& __vtable, + std::index_sequence<__var_indices...>) + { + if constexpr (__extra_visit_slot_needed<_Result_type, _Next>) + (_S_apply_single_alt( + __vtable._M_arr[__var_indices + 1], + &(__vtable._M_arr[0])), ...); + else + (_S_apply_single_alt( + __vtable._M_arr[__var_indices]), ...); + } + + template + static constexpr void + _S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr) + { + if constexpr (__do_cookie) + { + __element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., __index>>::_S_apply(); + *__cookie_element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., variant_npos>>::_S_apply(); + } + else + { + auto __tmp_element = __gen_vtable_impl< + remove_reference_t, + std::index_sequence<__indices..., __index>>::_S_apply(); + static_assert(is_same_v<_Tp, decltype(__tmp_element)>, + "std::visit requires the visitor to have the same " + "return type for all alternatives of a variant"); + __element = __tmp_element; + } + } + }; + + // This partial specialization is the base case for the recursion. + // It populates a _Multi_array element with the address of a function + // that invokes the visitor with the alternatives specified by __indices. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, + std::index_sequence<__indices...>> + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>; + + template + static constexpr decltype(auto) + __element_by_index_or_cookie(_Variant&& __var) noexcept + { + if constexpr (__index != variant_npos) + return __variant::__get<__index>(std::forward<_Variant>(__var)); + else + return __variant_cookie{}; + } + + static constexpr decltype(auto) + __visit_invoke(_Visitor&& __visitor, _Variants... __vars) + { + if constexpr (is_same_v<_Result_type, __variant_idx_cookie>) + // For raw visitation using indices, pass the indices to the visitor + // and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))..., + integral_constant()...); + else if constexpr (is_same_v<_Result_type, __variant_cookie>) + // For raw visitation without indices, and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else if constexpr (_Array_type::__result_is_deduced::value) + // For the usual std::visit case deduce the return value: + return std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else // for std::visit use INVOKE + return std::__invoke_r<_Result_type>( + std::forward<_Visitor>(__visitor), + __variant::__get<__indices>(std::forward<_Variants>(__vars))...); + } + + static constexpr auto + _S_apply() + { + if constexpr (_Array_type::__result_is_deduced::value) + { + constexpr bool __visit_ret_type_mismatch = + !is_same_v(), + std::declval<_Variants>()...))>; + if constexpr (__visit_ret_type_mismatch) + { + struct __cannot_match {}; + return __cannot_match{}; + } + else + return _Array_type{&__visit_invoke}; + } + else + return _Array_type{&__visit_invoke}; + } + }; + + template + struct __gen_vtable + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + variant_size_v>...>; + + static constexpr _Array_type _S_vtable + = __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply(); + }; + + template + struct _Base_dedup : public _Tp { }; + + template + struct _Variant_hash_base; + + template + struct _Variant_hash_base, + std::index_sequence<__indices...>> + : _Base_dedup<__indices, __poison_hash>>... { }; + + // Equivalent to decltype(get<_Np>(as-variant(declval<_Variant>()))) + template())), + typename _Tp = variant_alternative_t<_Np, remove_reference_t<_AsV>>> + using __get_t + = __conditional_t, _Tp&, _Tp&&>; + + // Return type of std::visit. + template + using __visit_result_t + = invoke_result_t<_Visitor, __get_t<0, _Variants>...>; + + template + constexpr inline bool __same_types = (is_same_v<_Tp, _Types> && ...); + + template + constexpr bool __check_visitor_results(std::index_sequence<_Idxs...>) + { + return __same_types< + invoke_result_t<_Visitor, __get_t<_Idxs, _Variant>>... + >; + } + +} // namespace __variant +} // namespace __detail + + template + constexpr bool + holds_alternative(const variant<_Types...>& __v) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + return __v.index() == std::__find_uniq_type_in_pack<_Tp, _Types...>(); + } + + template + constexpr _Tp& + get(variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get<__n>(__v); + } + + template + constexpr _Tp&& + get(variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get<__n>(std::move(__v)); + } + + template + constexpr const _Tp& + get(const variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get<__n>(__v); + } + + template + constexpr const _Tp&& + get(const variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get<__n>(std::move(__v)); + } + + template + constexpr add_pointer_t>> + get_if(variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr + add_pointer_t>> + get_if(const variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr add_pointer_t<_Tp> + get_if(variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get_if<__n>(__ptr); + } + + template + constexpr add_pointer_t + get_if(const variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + return std::get_if<__n>(__ptr); + } + + struct monostate { }; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + constexpr bool operator __OP(const variant<_Types...>& __lhs, \ + const variant<_Types...>& __rhs) \ + { \ + bool __ret = true; \ + __detail::__variant::__raw_idx_visit( \ + [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \ + { \ + if constexpr (__rhs_index != variant_npos) \ + { \ + if (__lhs.index() == __rhs_index) \ + { \ + auto& __this_mem = std::get<__rhs_index>(__lhs); \ + __ret = __this_mem __OP __rhs_mem; \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + }, __rhs); \ + return __ret; \ + } + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + + constexpr bool operator==(monostate, monostate) noexcept { return true; } + +#ifdef __cpp_lib_three_way_comparison + template + requires (three_way_comparable<_Types> && ...) + constexpr + common_comparison_category_t...> + operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w) + { + common_comparison_category_t...> __ret + = strong_ordering::equal; + + __detail::__variant::__raw_idx_visit( + [&__ret, &__v] (auto&& __w_mem, auto __w_index) mutable + { + if constexpr (__w_index != variant_npos) + { + if (__v.index() == __w_index) + { + auto& __this_mem = std::get<__w_index>(__v); + __ret = __this_mem <=> __w_mem; + return; + } + } + __ret = (__v.index() + 1) <=> (__w_index + 1); + }, __w); + return __ret; + } + + constexpr strong_ordering + operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } +#else + constexpr bool operator!=(monostate, monostate) noexcept { return false; } + constexpr bool operator<(monostate, monostate) noexcept { return false; } + constexpr bool operator>(monostate, monostate) noexcept { return false; } + constexpr bool operator<=(monostate, monostate) noexcept { return true; } + constexpr bool operator>=(monostate, monostate) noexcept { return true; } +#endif + + template + constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> + visit(_Visitor&&, _Variants&&...); + + template + _GLIBCXX20_CONSTEXPR + inline enable_if_t<(is_move_constructible_v<_Types> && ...) + && (is_swappable_v<_Types> && ...)> + swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && ...) + && (is_swappable_v<_Types> && ...))> + swap(variant<_Types...>&, variant<_Types...>&) = delete; + + class bad_variant_access : public exception + { + public: + bad_variant_access() noexcept { } + + const char* what() const noexcept override + { return _M_reason; } + + private: + bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { } + + // Must point to a string with static storage duration: + const char* _M_reason = "bad variant access"; + + friend void __throw_bad_variant_access(const char* __what); + }; + + // Must only be called with a string literal + inline void + __throw_bad_variant_access(const char* __what) + { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); } + + inline void + __throw_bad_variant_access(bool __valueless) + { + if (__valueless) [[__unlikely__]] + __throw_bad_variant_access("std::get: variant is valueless"); + else + __throw_bad_variant_access("std::get: wrong index for variant"); + } + + template + class variant + : private __detail::__variant::_Variant_base<_Types...>, + private _Enable_copy_move< + __detail::__variant::_Traits<_Types...>::_S_copy_ctor, + __detail::__variant::_Traits<_Types...>::_S_copy_assign, + __detail::__variant::_Traits<_Types...>::_S_move_ctor, + __detail::__variant::_Traits<_Types...>::_S_move_assign, + variant<_Types...>> + { + private: + template + friend _GLIBCXX20_CONSTEXPR decltype(auto) + __variant_cast(_Tp&&); + + static_assert(sizeof...(_Types) > 0, + "variant must have at least one alternative"); + static_assert(!(std::is_reference_v<_Types> || ...), + "variant must have no reference alternative"); + static_assert(!(std::is_void_v<_Types> || ...), + "variant must have no void alternative"); + + using _Base = __detail::__variant::_Variant_base<_Types...>; + + template + static constexpr bool __not_self + = !is_same_v<__remove_cvref_t<_Tp>, variant>; + + template + static constexpr bool + __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; + + template + static constexpr size_t __accepted_index + = __detail::__variant::__accepted_index<_Tp, variant>; + + template> + using __to_type = typename _Nth_type<_Np, _Types...>::type; + + template>> + using __accepted_type = __to_type<__accepted_index<_Tp>>; + + template + static constexpr size_t __index_of + = std::__find_uniq_type_in_pack<_Tp, _Types...>(); + + using _Traits = __detail::__variant::_Traits<_Types...>; + + template + struct __is_in_place_tag : false_type { }; + template + struct __is_in_place_tag> : true_type { }; + template + struct __is_in_place_tag> : true_type { }; + + template + static constexpr bool __not_in_place_tag + = !__is_in_place_type_v<__remove_cvref_t<_Tp>> + && !__is_in_place_index_v<__remove_cvref_t<_Tp>>; + + public: +#if __cpp_concepts + variant() requires is_default_constructible_v<__to_type<0>> = default; +#else + template, + typename = enable_if_t>> + constexpr + variant() noexcept(is_nothrow_default_constructible_v<__to_type<0>>) + { } +#endif + + variant(const variant& __rhs) = default; + variant(variant&&) = default; + variant& operator=(const variant&) = default; + variant& operator=(variant&&) = default; + _GLIBCXX20_CONSTEXPR ~variant() = default; + + template, + typename = enable_if_t<__not_in_place_tag<_Tp>>, + typename _Tj = __accepted_type<_Tp&&>, + typename = enable_if_t<__exactly_once<_Tj> + && is_constructible_v<_Tj, _Tp>>> + constexpr + variant(_Tp&& __t) + noexcept(is_nothrow_constructible_v<_Tj, _Tp>) + : variant(in_place_index<__accepted_index<_Tp>>, + std::forward<_Tp>(__t)) + { } + + template + && is_constructible_v<_Tp, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, + std::forward<_Args>(__args)...) + { } + + template + && is_constructible_v<_Tp, + initializer_list<_Up>&, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, + _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, __il, + std::forward<_Args>(__args)...) + { } + + template, + typename = enable_if_t>> + constexpr explicit + variant(in_place_index_t<_Np>, _Args&&... __args) + : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...) + { } + + template, + typename = enable_if_t&, + _Args...>>> + constexpr explicit + variant(in_place_index_t<_Np>, initializer_list<_Up> __il, + _Args&&... __args) + : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...) + { } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t<__exactly_once<__accepted_type<_Tp&&>> + && is_constructible_v<__accepted_type<_Tp&&>, _Tp> + && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>, + variant&> + operator=(_Tp&& __rhs) + noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp> + && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) + { + constexpr auto __index = __accepted_index<_Tp>; + if (index() == __index) + std::get<__index>(*this) = std::forward<_Tp>(__rhs); + else + { + using _Tj = __accepted_type<_Tp&&>; + if constexpr (is_nothrow_constructible_v<_Tj, _Tp> + || !is_nothrow_move_constructible_v<_Tj>) + this->emplace<__index>(std::forward<_Tp>(__rhs)); + else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3585. converting assignment with immovable alternative + this->emplace<__index>(_Tj(std::forward<_Tp>(__rhs))); + } + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t && __exactly_once<_Tp>, + _Tp&> + emplace(_Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(std::forward<_Args>(__args)...); + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t&, _Args...> + && __exactly_once<_Tp>, + _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(__il, std::forward<_Args>(__args)...); + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t, _Args...>, + __to_type<_Np>&> + emplace(_Args&&... __args) + { + namespace __variant = std::__detail::__variant; + using type = typename _Nth_type<_Np, _Types...>::type; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v) + { + __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...); + } + else if constexpr (is_scalar_v) + { + // This might invoke a potentially-throwing conversion operator: + const type __tmp(std::forward<_Args>(__args)...); + // But this won't throw: + __variant::__emplace<_Np>(*this, __tmp); + } + else if constexpr (__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...); + } + return std::get<_Np>(*this); + } + + template + _GLIBCXX20_CONSTEXPR + enable_if_t, + initializer_list<_Up>&, _Args...>, + __to_type<_Np>&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + namespace __variant = std::__detail::__variant; + using type = typename _Nth_type<_Np, _Types...>::type; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v&, + _Args...>) + { + __variant::__emplace<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + else if constexpr (__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, __il, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + __variant::__emplace<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + return std::get<_Np>(*this); + } + + template + enable_if_t emplace(_Args&&...) = delete; + + template + enable_if_t> emplace(_Args&&...) = delete; + + constexpr bool valueless_by_exception() const noexcept + { return !this->_M_valid(); } + + constexpr size_t index() const noexcept + { + using __index_type = typename _Base::__index_type; + if constexpr (__detail::__variant::__never_valueless<_Types...>()) + return this->_M_index; + else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2) + return make_signed_t<__index_type>(this->_M_index); + else + return size_t(__index_type(this->_M_index + 1)) - 1; + } + + _GLIBCXX20_CONSTEXPR + void + swap(variant& __rhs) + noexcept((__is_nothrow_swappable<_Types>::value && ...) + && is_nothrow_move_constructible_v) + { + static_assert((is_move_constructible_v<_Types> && ...)); + + // Handle this here to simplify the visitation. + if (__rhs.valueless_by_exception()) [[__unlikely__]] + { + if (!this->valueless_by_exception()) [[__likely__]] + __rhs.swap(*this); + return; + } + + namespace __variant = __detail::__variant; + + __variant::__raw_idx_visit( + [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable + { + constexpr size_t __j = __rhs_index; + if constexpr (__j != variant_npos) + { + if (this->index() == __j) + { + using std::swap; + swap(std::get<__j>(*this), __rhs_mem); + } + else + { + auto __tmp(std::move(__rhs_mem)); + + if constexpr (_Traits::_S_trivial_move_assign) + __rhs = std::move(*this); + else + __variant::__raw_idx_visit( + [&__rhs](auto&& __this_mem, auto __this_index) mutable + { + constexpr size_t __k = __this_index; + if constexpr (__k != variant_npos) + __variant::__emplace<__k>(__rhs, + std::move(__this_mem)); + }, *this); + + __variant::__emplace<__j>(*this, std::move(__tmp)); + } + } + }, __rhs); + } + +#if defined(__clang__) && __clang_major__ <= 7 + public: + using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 +#endif + + private: + template + friend constexpr decltype(auto) + __detail::__variant::__get(_Vp&& __v) noexcept; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ + template \ + friend constexpr bool \ + operator __OP(const variant<_Tp...>& __lhs, \ + const variant<_Tp...>& __rhs); + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + }; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>& + get(const variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>&& + get(const variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + /// @cond undocumented + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + // Get the silly case of visiting no variants out of the way first. + if constexpr (sizeof...(_Variants) == 0) + { + if constexpr (is_void_v<_Result_type>) + return (void) std::forward<_Visitor>(__visitor)(); + else + return std::forward<_Visitor>(__visitor)(); + } + else + { + constexpr size_t __max = 11; // "These go to eleven." + + // The type of the first variant in the pack. + using _V0 = typename _Nth_type<0, _Variants...>::type; + // The number of alternatives in that first variant. + constexpr auto __n = variant_size_v>; + + if constexpr (sizeof...(_Variants) > 1 || __n > __max) + { + // Use a jump table for the general case. + constexpr auto& __vtable = __detail::__variant::__gen_vtable< + _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; + + auto __func_ptr = __vtable._M_access(__variants.index()...); + return (*__func_ptr)(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + else // We have a single variant with a small number of alternatives. + { + // A name for the first variant in the pack. + _V0& __v0 + = [](_V0& __v, ...) -> _V0& { return __v; }(__variants...); + + using __detail::__variant::_Multi_array; + using __detail::__variant::__gen_vtable_impl; + using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0&&)>; + +#ifdef _GLIBCXX_DEBUG +# define _GLIBCXX_VISIT_UNREACHABLE __builtin_trap +#else +# define _GLIBCXX_VISIT_UNREACHABLE __builtin_unreachable +#endif + +#define _GLIBCXX_VISIT_CASE(N) \ + case N: \ + { \ + if constexpr (N < __n) \ + { \ + return __gen_vtable_impl<_Ma, index_sequence>:: \ + __visit_invoke(std::forward<_Visitor>(__visitor), \ + std::forward<_V0>(__v0)); \ + } \ + else _GLIBCXX_VISIT_UNREACHABLE(); \ + } + + switch (__v0.index()) + { + _GLIBCXX_VISIT_CASE(0) + _GLIBCXX_VISIT_CASE(1) + _GLIBCXX_VISIT_CASE(2) + _GLIBCXX_VISIT_CASE(3) + _GLIBCXX_VISIT_CASE(4) + _GLIBCXX_VISIT_CASE(5) + _GLIBCXX_VISIT_CASE(6) + _GLIBCXX_VISIT_CASE(7) + _GLIBCXX_VISIT_CASE(8) + _GLIBCXX_VISIT_CASE(9) + _GLIBCXX_VISIT_CASE(10) + case variant_npos: + using __detail::__variant::__variant_idx_cookie; + using __detail::__variant::__variant_cookie; + if constexpr (is_same_v<_Result_type, __variant_idx_cookie> + || is_same_v<_Result_type, __variant_cookie>) + { + using _Npos = index_sequence; + return __gen_vtable_impl<_Ma, _Npos>:: + __visit_invoke(std::forward<_Visitor>(__visitor), + std::forward<_V0>(__v0)); + } + else + _GLIBCXX_VISIT_UNREACHABLE(); + default: + _GLIBCXX_VISIT_UNREACHABLE(); + } +#undef _GLIBCXX_VISIT_CASE +#undef _GLIBCXX_VISIT_UNREACHABLE + } + } + } + /// @endcond + + template + constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + namespace __variant = std::__detail::__variant; + + if ((__variant::__as(__variants).valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + using _Result_type + = __detail::__variant::__visit_result_t<_Visitor, _Variants...>; + + using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>; + + if constexpr (sizeof...(_Variants) == 1) + { + using _Vp = decltype(__variant::__as(std::declval<_Variants>()...)); + + constexpr bool __visit_rettypes_match = __detail::__variant:: + __check_visitor_results<_Visitor, _Vp>( + make_index_sequence>>()); + if constexpr (!__visit_rettypes_match) + { + static_assert(__visit_rettypes_match, + "std::visit requires the visitor to have the same " + "return type for all alternatives of a variant"); + return; + } + else + return std::__do_visit<_Tag>( + std::forward<_Visitor>(__visitor), + static_cast<_Vp>(__variants)...); + } + else + return std::__do_visit<_Tag>( + std::forward<_Visitor>(__visitor), + __variant::__as(std::forward<_Variants>(__variants))...); + } + +#if __cplusplus > 201703L + template + constexpr _Res + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + namespace __variant = std::__detail::__variant; + + if ((__variant::__as(__variants).valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), + __variant::__as(std::forward<_Variants>(__variants))...); + } +#endif + + /// @cond undocumented + template + struct __variant_hash_call_base_impl + { + size_t + operator()(const variant<_Types...>& __t) const + noexcept((is_nothrow_invocable_v>, _Types> && ...)) + { + size_t __ret; + __detail::__variant::__raw_visit( + [&__t, &__ret](auto&& __t_mem) mutable + { + using _Type = __remove_cvref_t; + if constexpr (!is_same_v<_Type, + __detail::__variant::__variant_cookie>) + __ret = std::hash{}(__t.index()) + + std::hash<_Type>{}(__t_mem); + else + __ret = std::hash{}(__t.index()); + }, __t); + return __ret; + } + }; + + template + struct __variant_hash_call_base_impl {}; + + template + using __variant_hash_call_base = + __variant_hash_call_base_impl<(__poison_hash>:: + __enable_hash_call &&...), _Types...>; + /// @endcond + + template + struct hash> + : private __detail::__variant::_Variant_hash_base< + variant<_Types...>, std::index_sequence_for<_Types...>>, + public __variant_hash_call_base<_Types...> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = variant<_Types...>; + }; + + template<> + struct hash + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = monostate; + + size_t + operator()(const monostate&) const noexcept + { + constexpr size_t __magic_monostate_hash = -7777; + return __magic_monostate_hash; + } + }; + + template + struct __is_fast_hash>> + : bool_constant<(__is_fast_hash<_Types>::value && ...)> + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_variant +#endif // _GLIBCXX_VARIANT diff --git a/template/sysroot/include/version b/template/sysroot/include/version new file mode 100644 index 0000000..47c10d6 --- /dev/null +++ b/template/sysroot/include/version @@ -0,0 +1,38 @@ +// -*- C++ -*- Libstdc++ version details header. + +// Copyright (C) 2018-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file version + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + */ + +#ifndef _GLIBCXX_VERSION_INCLUDED +#define _GLIBCXX_VERSION_INCLUDED + +#pragma GCC system_header + +#define __glibcxx_want_all +#include + +#endif // _GLIBCXX_VERSION_INCLUDED diff --git a/template/sysroot/include/vpclmulqdqintrin.h b/template/sysroot/include/vpclmulqdqintrin.h new file mode 100644 index 0000000..0aad6db --- /dev/null +++ b/template/sysroot/include/vpclmulqdqintrin.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _VPCLMULQDQINTRIN_H_INCLUDED +#define _VPCLMULQDQINTRIN_H_INCLUDED + +#if !defined(__VPCLMULQDQ__) || !defined(__AVX512F__) || !defined(__EVEX512__) +#pragma GCC push_options +#pragma GCC target("vpclmulqdq,avx512f,evex512") +#define __DISABLE_VPCLMULQDQF__ +#endif /* __VPCLMULQDQF__ */ + +#ifdef __OPTIMIZE__ +extern __inline __m512i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_clmulepi64_epi128 (__m512i __A, __m512i __B, const int __C) +{ + return (__m512i) __builtin_ia32_vpclmulqdq_v8di ((__v8di)__A, + (__v8di) __B, __C); +} +#else +#define _mm512_clmulepi64_epi128(A, B, C) \ + ((__m512i) __builtin_ia32_vpclmulqdq_v8di ((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(C))) +#endif + +#ifdef __DISABLE_VPCLMULQDQF__ +#undef __DISABLE_VPCLMULQDQF__ +#pragma GCC pop_options +#endif /* __DISABLE_VPCLMULQDQF__ */ + +#if !defined(__VPCLMULQDQ__) +#pragma GCC push_options +#pragma GCC target("vpclmulqdq") +#define __DISABLE_VPCLMULQDQ__ +#endif /* __VPCLMULQDQ__ */ + +#ifdef __OPTIMIZE__ +extern __inline __m256i +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_clmulepi64_epi128 (__m256i __A, __m256i __B, const int __C) +{ + return (__m256i) __builtin_ia32_vpclmulqdq_v4di ((__v4di)__A, + (__v4di) __B, __C); +} +#else +#define _mm256_clmulepi64_epi128(A, B, C) \ + ((__m256i) __builtin_ia32_vpclmulqdq_v4di ((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), (int)(C))) +#endif + +#ifdef __DISABLE_VPCLMULQDQ__ +#undef __DISABLE_VPCLMULQDQ__ +#pragma GCC pop_options +#endif /* __DISABLE_VPCLMULQDQ__ */ + +#endif /* _VPCLMULQDQINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/waitpkgintrin.h b/template/sysroot/include/waitpkgintrin.h new file mode 100644 index 0000000..00b1829 --- /dev/null +++ b/template/sysroot/include/waitpkgintrin.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _WAITPKG_H_INCLUDED +#define _WAITPKG_H_INCLUDED + +#ifndef __WAITPKG__ +#pragma GCC push_options +#pragma GCC target("waitpkg") +#define __DISABLE_WAITPKG__ +#endif /* __WAITPKG__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_umonitor (void *__A) +{ + __builtin_ia32_umonitor (__A); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_umwait (unsigned int __A, unsigned long long __B) +{ + return __builtin_ia32_umwait (__A, __B); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_tpause (unsigned int __A, unsigned long long __B) +{ + return __builtin_ia32_tpause (__A, __B); +} + +#ifdef __DISABLE_WAITPKG__ +#undef __DISABLE_WAITPKG__ +#pragma GCC pop_options +#endif /* __DISABLE_WAITPKG__ */ + +#endif /* _WAITPKG_H_INCLUDED. */ diff --git a/template/sysroot/include/wbnoinvdintrin.h b/template/sysroot/include/wbnoinvdintrin.h new file mode 100644 index 0000000..c3ef577 --- /dev/null +++ b/template/sysroot/include/wbnoinvdintrin.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2018-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _WBNOINVDINTRIN_H_INCLUDED +#define _WBNOINVDINTRIN_H_INCLUDED + +#ifndef __WBNOINVD__ +#pragma GCC push_options +#pragma GCC target("wbnoinvd") +#define __DISABLE_WBNOINVD__ +#endif /* __WBNOINVD__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wbnoinvd (void) +{ + __builtin_ia32_wbnoinvd (); +} + +#ifdef __DISABLE_WBNOINVD__ +#undef __DISABLE_WBNOINVD__ +#pragma GCC pop_options +#endif /* __DISABLE_WBNOINVD__ */ + +#endif /* _WBNOINVDINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/wmmintrin.h b/template/sysroot/include/wmmintrin.h new file mode 100644 index 0000000..34ddd3e --- /dev/null +++ b/template/sysroot/include/wmmintrin.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2008-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 10.1. */ + +#ifndef _WMMINTRIN_H_INCLUDED +#define _WMMINTRIN_H_INCLUDED + +/* We need definitions from the SSE2 header file. */ +#include + +/* AES */ + +#if !defined(__AES__) || !defined(__SSE2__) +#pragma GCC push_options +#pragma GCC target("aes,sse2") +#define __DISABLE_AES__ +#endif /* __AES__ */ + +/* Performs 1 round of AES decryption of the first m128i using + the second m128i as a round key. */ +#define _mm_aesdec_si128(X, Y) \ + (__m128i) __builtin_ia32_aesdec128 ((__v2di) (X), (__v2di) (Y)) + +/* Performs the last round of AES decryption of the first m128i + using the second m128i as a round key. */ +#define _mm_aesdeclast_si128(X, Y) \ + (__m128i) __builtin_ia32_aesdeclast128 ((__v2di) (X), (__v2di) (Y)) + +/* Performs 1 round of AES encryption of the first m128i using + the second m128i as a round key. */ +#define _mm_aesenc_si128(X, Y) \ + (__m128i) __builtin_ia32_aesenc128 ((__v2di) (X), (__v2di) (Y)) + +/* Performs the last round of AES encryption of the first m128i + using the second m128i as a round key. */ +#define _mm_aesenclast_si128(X, Y) \ + (__m128i) __builtin_ia32_aesenclast128 ((__v2di) (X), (__v2di) (Y)) + +/* Performs the InverseMixColumn operation on the source m128i + and stores the result into m128i destination. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aesimc_si128 (__m128i __X) +{ + return (__m128i) __builtin_ia32_aesimc128 ((__v2di)__X); +} + +/* Generates a m128i round key for the input m128i AES cipher key and + byte round constant. The second parameter must be a compile time + constant. */ +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_aeskeygenassist_si128 (__m128i __X, const int __C) +{ + return (__m128i) __builtin_ia32_aeskeygenassist128 ((__v2di)__X, __C); +} +#else +#define _mm_aeskeygenassist_si128(X, C) \ + ((__m128i) __builtin_ia32_aeskeygenassist128 ((__v2di)(__m128i)(X), \ + (int)(C))) +#endif + +#ifdef __DISABLE_AES__ +#undef __DISABLE_AES__ +#pragma GCC pop_options +#endif /* __DISABLE_AES__ */ + +/* PCLMUL */ + +#if !defined(__PCLMUL__) || !defined(__SSE2__) +#pragma GCC push_options +#pragma GCC target("pclmul,sse2") +#define __DISABLE_PCLMUL__ +#endif /* __PCLMUL__ */ + +/* Performs carry-less integer multiplication of 64-bit halves of + 128-bit input operands. The third parameter inducates which 64-bit + haves of the input parameters v1 and v2 should be used. It must be + a compile time constant. */ +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_clmulepi64_si128 (__m128i __X, __m128i __Y, const int __I) +{ + return (__m128i) __builtin_ia32_pclmulqdq128 ((__v2di)__X, + (__v2di)__Y, __I); +} +#else +#define _mm_clmulepi64_si128(X, Y, I) \ + ((__m128i) __builtin_ia32_pclmulqdq128 ((__v2di)(__m128i)(X), \ + (__v2di)(__m128i)(Y), (int)(I))) +#endif + +#ifdef __DISABLE_PCLMUL__ +#undef __DISABLE_PCLMUL__ +#pragma GCC pop_options +#endif /* __DISABLE_PCLMUL__ */ + +#endif /* _WMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/x86gprintrin.h b/template/sysroot/include/x86gprintrin.h new file mode 100644 index 0000000..015ee6d --- /dev/null +++ b/template/sysroot/include/x86gprintrin.h @@ -0,0 +1,277 @@ +/* Copyright (C) 2020-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +#define _X86GPRINTRIN_H_INCLUDED + +#if !defined _SOFT_FLOAT || defined __MMX__ || defined __SSE__ +#pragma GCC push_options +#pragma GCC target("general-regs-only") +#define __DISABLE_GENERAL_REGS_ONLY__ +#endif + +#include + +#ifndef __iamcu__ + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_wbinvd (void) +{ + __builtin_ia32_wbinvd (); +} + +#ifndef __RDRND__ +#pragma GCC push_options +#pragma GCC target("rdrnd") +#define __DISABLE_RDRND__ +#endif /* __RDRND__ */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdrand16_step (unsigned short *__P) +{ + return __builtin_ia32_rdrand16_step (__P); +} + +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdrand32_step (unsigned int *__P) +{ + return __builtin_ia32_rdrand32_step (__P); +} +#ifdef __DISABLE_RDRND__ +#undef __DISABLE_RDRND__ +#pragma GCC pop_options +#endif /* __DISABLE_RDRND__ */ + +#ifndef __RDPID__ +#pragma GCC push_options +#pragma GCC target("rdpid") +#define __DISABLE_RDPID__ +#endif /* __RDPID__ */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdpid_u32 (void) +{ + return __builtin_ia32_rdpid (); +} +#ifdef __DISABLE_RDPID__ +#undef __DISABLE_RDPID__ +#pragma GCC pop_options +#endif /* __DISABLE_RDPID__ */ + +#ifdef __x86_64__ + +#ifndef __FSGSBASE__ +#pragma GCC push_options +#pragma GCC target("fsgsbase") +#define __DISABLE_FSGSBASE__ +#endif /* __FSGSBASE__ */ +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_readfsbase_u32 (void) +{ + return __builtin_ia32_rdfsbase32 (); +} + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_readfsbase_u64 (void) +{ + return __builtin_ia32_rdfsbase64 (); +} + +extern __inline unsigned int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_readgsbase_u32 (void) +{ + return __builtin_ia32_rdgsbase32 (); +} + +extern __inline unsigned long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_readgsbase_u64 (void) +{ + return __builtin_ia32_rdgsbase64 (); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_writefsbase_u32 (unsigned int __B) +{ + __builtin_ia32_wrfsbase32 (__B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_writefsbase_u64 (unsigned long long __B) +{ + __builtin_ia32_wrfsbase64 (__B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_writegsbase_u32 (unsigned int __B) +{ + __builtin_ia32_wrgsbase32 (__B); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_writegsbase_u64 (unsigned long long __B) +{ + __builtin_ia32_wrgsbase64 (__B); +} +#ifdef __DISABLE_FSGSBASE__ +#undef __DISABLE_FSGSBASE__ +#pragma GCC pop_options +#endif /* __DISABLE_FSGSBASE__ */ + +#ifndef __RDRND__ +#pragma GCC push_options +#pragma GCC target("rdrnd") +#define __DISABLE_RDRND__ +#endif /* __RDRND__ */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_rdrand64_step (unsigned long long *__P) +{ + return __builtin_ia32_rdrand64_step (__P); +} +#ifdef __DISABLE_RDRND__ +#undef __DISABLE_RDRND__ +#pragma GCC pop_options +#endif /* __DISABLE_RDRND__ */ + +#endif /* __x86_64__ */ + +#ifndef __PTWRITE__ +#pragma GCC push_options +#pragma GCC target("ptwrite") +#define __DISABLE_PTWRITE__ +#endif + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_ptwrite64 (unsigned long long __B) +{ + __builtin_ia32_ptwrite64 (__B); +} +#endif /* __x86_64__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_ptwrite32 (unsigned __B) +{ + __builtin_ia32_ptwrite32 (__B); +} +#ifdef __DISABLE_PTWRITE__ +#undef __DISABLE_PTWRITE__ +#pragma GCC pop_options +#endif /* __DISABLE_PTWRITE__ */ + +#endif /* __iamcu__ */ + +#ifdef __DISABLE_GENERAL_REGS_ONLY__ +#undef __DISABLE_GENERAL_REGS_ONLY__ +#pragma GCC pop_options +#endif /* __DISABLE_GENERAL_REGS_ONLY__ */ + +#endif /* _X86GPRINTRIN_H_INCLUDED. */ diff --git a/template/sysroot/include/x86intrin.h b/template/sysroot/include/x86intrin.h new file mode 100644 index 0000000..f41ce43 --- /dev/null +++ b/template/sysroot/include/x86intrin.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2008-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86INTRIN_H_INCLUDED +#define _X86INTRIN_H_INCLUDED + +#include + +#ifndef __iamcu__ + +/* For including AVX instructions */ +#include + +#include + +#include + +#include + +#endif /* __iamcu__ */ + +#endif /* _X86INTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xmmintrin.h b/template/sysroot/include/xmmintrin.h new file mode 100644 index 0000000..71b9955 --- /dev/null +++ b/template/sysroot/include/xmmintrin.h @@ -0,0 +1,1340 @@ +/* Copyright (C) 2002-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* Implemented from the specification included in the Intel C++ Compiler + User Guide and Reference, version 9.0. */ + +#ifndef _XMMINTRIN_H_INCLUDED +#define _XMMINTRIN_H_INCLUDED + +/* We need type definitions from the MMX header file. */ +#include + +/* Get _mm_malloc () and _mm_free (). */ +#include + +/* Constants for use with _mm_prefetch. */ +enum _mm_hint +{ + _MM_HINT_IT0 = 19, + _MM_HINT_IT1 = 18, + /* _MM_HINT_ET is _MM_HINT_T with set 3rd bit. */ + _MM_HINT_ET0 = 7, + _MM_HINT_ET1 = 6, + _MM_HINT_T0 = 3, + _MM_HINT_T1 = 2, + _MM_HINT_T2 = 1, + _MM_HINT_NTA = 0 +}; + +/* Loads one cache line from address P to a location "closer" to the + processor. The selector I specifies the type of prefetch operation. */ +#ifdef __OPTIMIZE__ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_prefetch (const void *__P, enum _mm_hint __I) +{ + __builtin_ia32_prefetch (__P, (__I & 0x4) >> 2, + __I & 0x3, (__I & 0x10) >> 4); +} +#else +#define _mm_prefetch(P, I) \ + __builtin_ia32_prefetch ((P), ((I) & 0x4) >> 2, ((I) & 0x3), ((I) & 0x10) >> 4) +#endif + +#ifndef __SSE__ +#pragma GCC push_options +#pragma GCC target("sse") +#define __DISABLE_SSE__ +#endif /* __SSE__ */ + +/* The Intel API is flexible enough that we must allow aliasing with other + vector types, and their scalar components. */ +typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); + +/* Unaligned version of the same type. */ +typedef float __m128_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1))); + +/* Internal data types for implementing the intrinsics. */ +typedef float __v4sf __attribute__ ((__vector_size__ (16))); + +/* Create a selector for use with the SHUFPS instruction. */ +#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \ + (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0)) + +/* Bits in the MXCSR. */ +#define _MM_EXCEPT_MASK 0x003f +#define _MM_EXCEPT_INVALID 0x0001 +#define _MM_EXCEPT_DENORM 0x0002 +#define _MM_EXCEPT_DIV_ZERO 0x0004 +#define _MM_EXCEPT_OVERFLOW 0x0008 +#define _MM_EXCEPT_UNDERFLOW 0x0010 +#define _MM_EXCEPT_INEXACT 0x0020 + +#define _MM_MASK_MASK 0x1f80 +#define _MM_MASK_INVALID 0x0080 +#define _MM_MASK_DENORM 0x0100 +#define _MM_MASK_DIV_ZERO 0x0200 +#define _MM_MASK_OVERFLOW 0x0400 +#define _MM_MASK_UNDERFLOW 0x0800 +#define _MM_MASK_INEXACT 0x1000 + +#define _MM_ROUND_MASK 0x6000 +#define _MM_ROUND_NEAREST 0x0000 +#define _MM_ROUND_DOWN 0x2000 +#define _MM_ROUND_UP 0x4000 +#define _MM_ROUND_TOWARD_ZERO 0x6000 + +#define _MM_FLUSH_ZERO_MASK 0x8000 +#define _MM_FLUSH_ZERO_ON 0x8000 +#define _MM_FLUSH_ZERO_OFF 0x0000 + +/* Create an undefined vector. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_undefined_ps (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-self" + __m128 __Y = __Y; +#pragma GCC diagnostic pop + return __Y; +} + +/* Create a vector of zeros. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_ps (void) +{ + return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f }; +} + +/* Perform the respective operation on the lower SPFP (single-precision + floating-point) values of A and B; the upper three SPFP values are + passed through from A. */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_addss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_subss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_mulss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_divss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_ss (__m128 __A) +{ + return (__m128) __builtin_ia32_sqrtss ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp_ss (__m128 __A) +{ + return (__m128) __builtin_ia32_rcpss ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt_ss (__m128 __A) +{ + return (__m128) __builtin_ia32_rsqrtss ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxss ((__v4sf)__A, (__v4sf)__B); +} + +/* Perform the respective operation on the four SPFP values in A and B. */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_add_ps (__m128 __A, __m128 __B) +{ + return (__m128) ((__v4sf)__A + (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sub_ps (__m128 __A, __m128 __B) +{ + return (__m128) ((__v4sf)__A - (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mul_ps (__m128 __A, __m128 __B) +{ + return (__m128) ((__v4sf)__A * (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_div_ps (__m128 __A, __m128 __B) +{ + return (__m128) ((__v4sf)__A / (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sqrt_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_sqrtps ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rcp_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_rcpps ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rsqrt_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_rsqrtps ((__v4sf)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_minps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_maxps ((__v4sf)__A, (__v4sf)__B); +} + +/* Perform logical bit-wise operations on 128-bit values. */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_and_ps (__m128 __A, __m128 __B) +{ + return __builtin_ia32_andps (__A, __B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_andnot_ps (__m128 __A, __m128 __B) +{ + return __builtin_ia32_andnps (__A, __B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_ps (__m128 __A, __m128 __B) +{ + return __builtin_ia32_orps (__A, __B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_ps (__m128 __A, __m128 __B) +{ + return __builtin_ia32_xorps (__A, __B); +} + +/* Perform a comparison on the lower SPFP values of A and B. If the + comparison is true, place a mask of all ones in the result, otherwise a + mask of zeros. The upper three SPFP values are passed through from A. */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpeqss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpltss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpless ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movss ((__v4sf) __A, + (__v4sf) + __builtin_ia32_cmpltss ((__v4sf) __B, + (__v4sf) + __A)); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movss ((__v4sf) __A, + (__v4sf) + __builtin_ia32_cmpless ((__v4sf) __B, + (__v4sf) + __A)); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpneqss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnlt_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpnltss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnle_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpnless ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpngt_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movss ((__v4sf) __A, + (__v4sf) + __builtin_ia32_cmpnltss ((__v4sf) __B, + (__v4sf) + __A)); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnge_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movss ((__v4sf) __A, + (__v4sf) + __builtin_ia32_cmpnless ((__v4sf) __B, + (__v4sf) + __A)); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpord_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpordss ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpunord_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpunordss ((__v4sf)__A, (__v4sf)__B); +} + +/* Perform a comparison on the four SPFP values of A and B. For each + element, if the comparison is true, place a mask of all ones in the + result, otherwise a mask of zeros. */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpeq_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpeqps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmplt_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpltps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmple_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpleps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpgt_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpgtps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpge_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpgeps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpneq_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpneqps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnlt_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpnltps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnle_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpnleps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpngt_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpngtps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpnge_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpngeps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpord_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpordps ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmpunord_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_cmpunordps ((__v4sf)__A, (__v4sf)__B); +} + +/* Compare the lower SPFP values of A and B and return 1 if true + and 0 if false. */ + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comieq_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comieq ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comilt_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comilt ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comile_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comile ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comigt_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comigt ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comige_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comige ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comineq_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_comineq ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomieq_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomieq ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomilt_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomilt ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomile_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomile ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomigt_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomigt ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomige_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomige ((__v4sf)__A, (__v4sf)__B); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_ucomineq_ss (__m128 __A, __m128 __B) +{ + return __builtin_ia32_ucomineq ((__v4sf)__A, (__v4sf)__B); +} + +/* Convert the lower SPFP value to a 32-bit integer according to the current + rounding mode. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_si32 (__m128 __A) +{ + return __builtin_ia32_cvtss2si ((__v4sf) __A); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_ss2si (__m128 __A) +{ + return _mm_cvtss_si32 (__A); +} + +#ifdef __x86_64__ +/* Convert the lower SPFP value to a 32-bit integer according to the + current rounding mode. */ + +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_si64 (__m128 __A) +{ + return __builtin_ia32_cvtss2si64 ((__v4sf) __A); +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_si64x (__m128 __A) +{ + return __builtin_ia32_cvtss2si64 ((__v4sf) __A); +} +#endif + +/* Convert the two lower SPFP values to 32-bit integers according to the + current rounding mode. Return the integers in packed form. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_pi32 (__m128 __A) +{ + return (__m64) __builtin_ia32_cvtps2pi ((__v4sf) __A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_ps2pi (__m128 __A) +{ + return _mm_cvtps_pi32 (__A); +} + +/* Truncate the lower SPFP value to a 32-bit integer. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_si32 (__m128 __A) +{ + return __builtin_ia32_cvttss2si ((__v4sf) __A); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_ss2si (__m128 __A) +{ + return _mm_cvttss_si32 (__A); +} + +#ifdef __x86_64__ +/* Truncate the lower SPFP value to a 32-bit integer. */ + +/* Intel intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_si64 (__m128 __A) +{ + return __builtin_ia32_cvttss2si64 ((__v4sf) __A); +} + +/* Microsoft intrinsic. */ +extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttss_si64x (__m128 __A) +{ + return __builtin_ia32_cvttss2si64 ((__v4sf) __A); +} +#endif + +/* Truncate the two lower SPFP values to 32-bit integers. Return the + integers in packed form. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvttps_pi32 (__m128 __A) +{ + return (__m64) __builtin_ia32_cvttps2pi ((__v4sf) __A); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtt_ps2pi (__m128 __A) +{ + return _mm_cvttps_pi32 (__A); +} + +/* Convert B to a SPFP value and insert it as element zero in A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi32_ss (__m128 __A, int __B) +{ + return (__m128) __builtin_ia32_cvtsi2ss ((__v4sf) __A, __B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_si2ss (__m128 __A, int __B) +{ + return _mm_cvtsi32_ss (__A, __B); +} + +#ifdef __x86_64__ +/* Convert B to a SPFP value and insert it as element zero in A. */ + +/* Intel intrinsic. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64_ss (__m128 __A, long long __B) +{ + return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B); +} + +/* Microsoft intrinsic. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtsi64x_ss (__m128 __A, long long __B) +{ + return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B); +} +#endif + +/* Convert the two 32-bit values in B to SPFP form and insert them + as the two lower elements in A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpi32_ps (__m128 __A, __m64 __B) +{ + return (__m128) __builtin_ia32_cvtpi2ps ((__v4sf) __A, (__v2si)__B); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvt_pi2ps (__m128 __A, __m64 __B) +{ + return _mm_cvtpi32_ps (__A, __B); +} + +/* Convert the four signed 16-bit values in A to SPFP form. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpi16_ps (__m64 __A) +{ + __v4hi __sign; + __v2si __hisi, __losi; + __v4sf __zero, __ra, __rb; + + /* This comparison against zero gives us a mask that can be used to + fill in the missing sign bits in the unpack operations below, so + that we get signed values after unpacking. */ + __sign = __builtin_ia32_pcmpgtw ((__v4hi)0LL, (__v4hi)__A); + + /* Convert the four words to doublewords. */ + __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, __sign); + __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, __sign); + + /* Convert the doublewords to floating point two at a time. */ + __zero = (__v4sf) _mm_setzero_ps (); + __ra = __builtin_ia32_cvtpi2ps (__zero, __losi); + __rb = __builtin_ia32_cvtpi2ps (__ra, __hisi); + + return (__m128) __builtin_ia32_movlhps (__ra, __rb); +} + +/* Convert the four unsigned 16-bit values in A to SPFP form. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpu16_ps (__m64 __A) +{ + __v2si __hisi, __losi; + __v4sf __zero, __ra, __rb; + + /* Convert the four words to doublewords. */ + __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, (__v4hi)0LL); + __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, (__v4hi)0LL); + + /* Convert the doublewords to floating point two at a time. */ + __zero = (__v4sf) _mm_setzero_ps (); + __ra = __builtin_ia32_cvtpi2ps (__zero, __losi); + __rb = __builtin_ia32_cvtpi2ps (__ra, __hisi); + + return (__m128) __builtin_ia32_movlhps (__ra, __rb); +} + +/* Convert the low four signed 8-bit values in A to SPFP form. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpi8_ps (__m64 __A) +{ + __v8qi __sign; + + /* This comparison against zero gives us a mask that can be used to + fill in the missing sign bits in the unpack operations below, so + that we get signed values after unpacking. */ + __sign = __builtin_ia32_pcmpgtb ((__v8qi)0LL, (__v8qi)__A); + + /* Convert the four low bytes to words. */ + __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, __sign); + + return _mm_cvtpi16_ps(__A); +} + +/* Convert the low four unsigned 8-bit values in A to SPFP form. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpu8_ps(__m64 __A) +{ + __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, (__v8qi)0LL); + return _mm_cvtpu16_ps(__A); +} + +/* Convert the four signed 32-bit values in A and B to SPFP form. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtpi32x2_ps(__m64 __A, __m64 __B) +{ + __v4sf __zero = (__v4sf) _mm_setzero_ps (); + __v4sf __sfa = __builtin_ia32_cvtpi2ps (__zero, (__v2si)__A); + __v4sf __sfb = __builtin_ia32_cvtpi2ps (__sfa, (__v2si)__B); + return (__m128) __builtin_ia32_movlhps (__sfa, __sfb); +} + +/* Convert the four SPFP values in A to four signed 16-bit integers. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_pi16(__m128 __A) +{ + __v4sf __hisf = (__v4sf)__A; + __v4sf __losf = __builtin_ia32_movhlps (__hisf, __hisf); + __v2si __hisi = __builtin_ia32_cvtps2pi (__hisf); + __v2si __losi = __builtin_ia32_cvtps2pi (__losf); + return (__m64) __builtin_ia32_packssdw (__hisi, __losi); +} + +/* Convert the four SPFP values in A to four signed 8-bit integers. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtps_pi8(__m128 __A) +{ + __v4hi __tmp = (__v4hi) _mm_cvtps_pi16 (__A); + return (__m64) __builtin_ia32_packsswb (__tmp, (__v4hi)0LL); +} + +/* Selects four specific SPFP values from A and B based on MASK. */ +#ifdef __OPTIMIZE__ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_ps (__m128 __A, __m128 __B, int const __mask) +{ + return (__m128) __builtin_ia32_shufps ((__v4sf)__A, (__v4sf)__B, __mask); +} +#else +#define _mm_shuffle_ps(A, B, MASK) \ + ((__m128) __builtin_ia32_shufps ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(MASK))) +#endif + +/* Selects and interleaves the upper two SPFP values from A and B. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpckhps ((__v4sf)__A, (__v4sf)__B); +} + +/* Selects and interleaves the lower two SPFP values from A and B. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_unpcklps ((__v4sf)__A, (__v4sf)__B); +} + +/* Sets the upper two SPFP values with 64-bits of data loaded from P; + the lower two values are passed through from A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadh_pi (__m128 __A, __m64 const *__P) +{ + return (__m128) __builtin_ia32_loadhps ((__v4sf)__A, (const __v2sf *)__P); +} + +/* Stores the upper two SPFP values of A into P. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeh_pi (__m64 *__P, __m128 __A) +{ + __builtin_ia32_storehps ((__v2sf *)__P, (__v4sf)__A); +} + +/* Moves the upper two values of B into the lower two values of A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movehl_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movhlps ((__v4sf)__A, (__v4sf)__B); +} + +/* Moves the lower two values of B into the upper two values of A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movelh_ps (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movlhps ((__v4sf)__A, (__v4sf)__B); +} + +/* Sets the lower two SPFP values with 64-bits of data loaded from P; + the upper two values are passed through from A. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadl_pi (__m128 __A, __m64 const *__P) +{ + return (__m128) __builtin_ia32_loadlps ((__v4sf)__A, (const __v2sf *)__P); +} + +/* Stores the lower two SPFP values of A into P. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storel_pi (__m64 *__P, __m128 __A) +{ + __builtin_ia32_storelps ((__v2sf *)__P, (__v4sf)__A); +} + +/* Creates a 4-bit mask from the most significant bits of the SPFP values. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_ps (__m128 __A) +{ + return __builtin_ia32_movmskps ((__v4sf)__A); +} + +/* Return the contents of the control register. */ +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_getcsr (void) +{ + return __builtin_ia32_stmxcsr (); +} + +/* Read exception bits from the control register. */ +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_GET_EXCEPTION_STATE (void) +{ + return _mm_getcsr() & _MM_EXCEPT_MASK; +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_GET_EXCEPTION_MASK (void) +{ + return _mm_getcsr() & _MM_MASK_MASK; +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_GET_ROUNDING_MODE (void) +{ + return _mm_getcsr() & _MM_ROUND_MASK; +} + +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_GET_FLUSH_ZERO_MODE (void) +{ + return _mm_getcsr() & _MM_FLUSH_ZERO_MASK; +} + +/* Set the control register to I. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setcsr (unsigned int __I) +{ + __builtin_ia32_ldmxcsr (__I); +} + +/* Set exception bits in the control register. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_SET_EXCEPTION_STATE(unsigned int __mask) +{ + _mm_setcsr((_mm_getcsr() & ~_MM_EXCEPT_MASK) | __mask); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_SET_EXCEPTION_MASK (unsigned int __mask) +{ + _mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | __mask); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_SET_ROUNDING_MODE (unsigned int __mode) +{ + _mm_setcsr((_mm_getcsr() & ~_MM_ROUND_MASK) | __mode); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_MM_SET_FLUSH_ZERO_MODE (unsigned int __mode) +{ + _mm_setcsr((_mm_getcsr() & ~_MM_FLUSH_ZERO_MASK) | __mode); +} + +/* Create a vector with element 0 as F and the rest zero. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_ss (float __F) +{ + return __extension__ (__m128)(__v4sf){ __F, 0.0f, 0.0f, 0.0f }; +} + +/* Create a vector with all four elements equal to F. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_ps (float __F) +{ + return __extension__ (__m128)(__v4sf){ __F, __F, __F, __F }; +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_ps1 (float __F) +{ + return _mm_set1_ps (__F); +} + +/* Create a vector with element 0 as *P and the rest zero. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_ss (float const *__P) +{ + return _mm_set_ss (*__P); +} + +/* Create a vector with all four elements equal to *P. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load1_ps (float const *__P) +{ + return _mm_set1_ps (*__P); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_ps1 (float const *__P) +{ + return _mm_load1_ps (__P); +} + +/* Load four SPFP values from P. The address must be 16-byte aligned. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_load_ps (float const *__P) +{ + return *(__m128 *)__P; +} + +/* Load four SPFP values from P. The address need not be 16-byte aligned. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadu_ps (float const *__P) +{ + return *(__m128_u *)__P; +} + +/* Load four SPFP values in reverse order. The address must be aligned. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_loadr_ps (float const *__P) +{ + __v4sf __tmp = *(__v4sf *)__P; + return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,1,2,3)); +} + +/* Create the vector [Z Y X W]. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W) +{ + return __extension__ (__m128)(__v4sf){ __W, __X, __Y, __Z }; +} + +/* Create the vector [W X Y Z]. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setr_ps (float __Z, float __Y, float __X, float __W) +{ + return __extension__ (__m128)(__v4sf){ __Z, __Y, __X, __W }; +} + +/* Stores the lower SPFP value. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_ss (float *__P, __m128 __A) +{ + *__P = ((__v4sf)__A)[0]; +} + +extern __inline float __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtss_f32 (__m128 __A) +{ + return ((__v4sf)__A)[0]; +} + +/* Store four SPFP values. The address must be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_ps (float *__P, __m128 __A) +{ + *(__m128 *)__P = __A; +} + +/* Store four SPFP values. The address need not be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_ps (float *__P, __m128 __A) +{ + *(__m128_u *)__P = __A; +} + +/* Store the lower SPFP value across four words. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store1_ps (float *__P, __m128 __A) +{ + __v4sf __va = (__v4sf)__A; + __v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,0,0,0)); + _mm_storeu_ps (__P, __tmp); +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_store_ps1 (float *__P, __m128 __A) +{ + _mm_store1_ps (__P, __A); +} + +/* Store four SPFP values in reverse order. The address must be aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storer_ps (float *__P, __m128 __A) +{ + __v4sf __va = (__v4sf)__A; + __v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,1,2,3)); + _mm_store_ps (__P, __tmp); +} + +/* Sets the low SPFP value of A from the low value of B. */ +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_move_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_shuffle ((__v4sf)__A, (__v4sf)__B, + __extension__ + (__attribute__((__vector_size__ (16))) int) + {4,1,2,3}); +} + +/* Extracts one of the four words of A. The selector N must be immediate. */ +#ifdef __OPTIMIZE__ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_extract_pi16 (__m64 const __A, int const __N) +{ + return (unsigned short) __builtin_ia32_vec_ext_v4hi ((__v4hi)__A, __N); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pextrw (__m64 const __A, int const __N) +{ + return _mm_extract_pi16 (__A, __N); +} +#else +#define _mm_extract_pi16(A, N) \ + ((int) (unsigned short) __builtin_ia32_vec_ext_v4hi ((__v4hi)(__m64)(A), (int)(N))) + +#define _m_pextrw(A, N) _mm_extract_pi16(A, N) +#endif + +/* Inserts word D into one of four words of A. The selector N must be + immediate. */ +#ifdef __OPTIMIZE__ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_insert_pi16 (__m64 const __A, int const __D, int const __N) +{ + return (__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)__A, __D, __N); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pinsrw (__m64 const __A, int const __D, int const __N) +{ + return _mm_insert_pi16 (__A, __D, __N); +} +#else +#define _mm_insert_pi16(A, D, N) \ + ((__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)(__m64)(A), \ + (int)(D), (int)(N))) + +#define _m_pinsrw(A, D, N) _mm_insert_pi16(A, D, N) +#endif + +/* Compute the element-wise maximum of signed 16-bit values. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_pi16 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pmaxsw ((__v4hi)__A, (__v4hi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmaxsw (__m64 __A, __m64 __B) +{ + return _mm_max_pi16 (__A, __B); +} + +/* Compute the element-wise maximum of unsigned 8-bit values. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_max_pu8 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pmaxub ((__v8qi)__A, (__v8qi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmaxub (__m64 __A, __m64 __B) +{ + return _mm_max_pu8 (__A, __B); +} + +/* Compute the element-wise minimum of signed 16-bit values. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_pi16 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pminsw ((__v4hi)__A, (__v4hi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pminsw (__m64 __A, __m64 __B) +{ + return _mm_min_pi16 (__A, __B); +} + +/* Compute the element-wise minimum of unsigned 8-bit values. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_min_pu8 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pminub ((__v8qi)__A, (__v8qi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pminub (__m64 __A, __m64 __B) +{ + return _mm_min_pu8 (__A, __B); +} + +/* Create an 8-bit mask of the signs of 8-bit values. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_pi8 (__m64 __A) +{ + return __builtin_ia32_pmovmskb ((__v8qi)__A); +} + +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmovmskb (__m64 __A) +{ + return _mm_movemask_pi8 (__A); +} + +/* Multiply four unsigned 16-bit values in A by four unsigned 16-bit values + in B and produce the high 16 bits of the 32-bit results. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhi_pu16 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pmulhuw ((__v4hi)__A, (__v4hi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pmulhuw (__m64 __A, __m64 __B) +{ + return _mm_mulhi_pu16 (__A, __B); +} + +/* Return a combination of the four 16-bit values in A. The selector + must be an immediate. */ +#ifdef __OPTIMIZE__ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_pi16 (__m64 __A, int const __N) +{ + return (__m64) __builtin_ia32_pshufw ((__v4hi)__A, __N); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pshufw (__m64 __A, int const __N) +{ + return _mm_shuffle_pi16 (__A, __N); +} +#else +#define _mm_shuffle_pi16(A, N) \ + ((__m64) __builtin_ia32_pshufw ((__v4hi)(__m64)(A), (int)(N))) + +#define _m_pshufw(A, N) _mm_shuffle_pi16 (A, N) +#endif + +/* Conditionally store byte elements of A into P. The high bit of each + byte in the selector N determines whether the corresponding byte from + A is stored. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maskmove_si64 (__m64 __A, __m64 __N, char *__P) +{ +#ifdef __MMX_WITH_SSE__ + /* Emulate MMX maskmovq with SSE2 maskmovdqu and handle unmapped bits + 64:127 at address __P. */ + typedef long long __v2di __attribute__ ((__vector_size__ (16))); + typedef char __v16qi __attribute__ ((__vector_size__ (16))); + /* Zero-extend __A and __N to 128 bits. */ + __v2di __A128 = __extension__ (__v2di) { ((__v1di) __A)[0], 0 }; + __v2di __N128 = __extension__ (__v2di) { ((__v1di) __N)[0], 0 }; + + /* Check the alignment of __P. */ + __SIZE_TYPE__ offset = ((__SIZE_TYPE__) __P) & 0xf; + if (offset) + { + /* If the misalignment of __P > 8, subtract __P by 8 bytes. + Otherwise, subtract __P by the misalignment. */ + if (offset > 8) + offset = 8; + __P = (char *) (((__SIZE_TYPE__) __P) - offset); + + /* Shift __A128 and __N128 to the left by the adjustment. */ + switch (offset) + { + case 1: + __A128 = __builtin_ia32_pslldqi128 (__A128, 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 8); + break; + case 2: + __A128 = __builtin_ia32_pslldqi128 (__A128, 2 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 2 * 8); + break; + case 3: + __A128 = __builtin_ia32_pslldqi128 (__A128, 3 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 3 * 8); + break; + case 4: + __A128 = __builtin_ia32_pslldqi128 (__A128, 4 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 4 * 8); + break; + case 5: + __A128 = __builtin_ia32_pslldqi128 (__A128, 5 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 5 * 8); + break; + case 6: + __A128 = __builtin_ia32_pslldqi128 (__A128, 6 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 6 * 8); + break; + case 7: + __A128 = __builtin_ia32_pslldqi128 (__A128, 7 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 7 * 8); + break; + case 8: + __A128 = __builtin_ia32_pslldqi128 (__A128, 8 * 8); + __N128 = __builtin_ia32_pslldqi128 (__N128, 8 * 8); + break; + default: + break; + } + } + __builtin_ia32_maskmovdqu ((__v16qi)__A128, (__v16qi)__N128, __P); +#else + __builtin_ia32_maskmovq ((__v8qi)__A, (__v8qi)__N, __P); +#endif +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_maskmovq (__m64 __A, __m64 __N, char *__P) +{ + _mm_maskmove_si64 (__A, __N, __P); +} + +/* Compute the rounded averages of the unsigned 8-bit values in A and B. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avg_pu8 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pavgb ((__v8qi)__A, (__v8qi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pavgb (__m64 __A, __m64 __B) +{ + return _mm_avg_pu8 (__A, __B); +} + +/* Compute the rounded averages of the unsigned 16-bit values in A and B. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_avg_pu16 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_pavgw ((__v4hi)__A, (__v4hi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_pavgw (__m64 __A, __m64 __B) +{ + return _mm_avg_pu16 (__A, __B); +} + +/* Compute the sum of the absolute differences of the unsigned 8-bit + values in A and B. Return the value in the lower 16-bit word; the + upper words are cleared. */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sad_pu8 (__m64 __A, __m64 __B) +{ + return (__m64) __builtin_ia32_psadbw ((__v8qi)__A, (__v8qi)__B); +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_m_psadbw (__m64 __A, __m64 __B) +{ + return _mm_sad_pu8 (__A, __B); +} + +/* Stores the data in A to the address P without polluting the caches. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_pi (__m64 *__P, __m64 __A) +{ + __builtin_ia32_movntq ((unsigned long long *)__P, (unsigned long long)__A); +} + +/* Likewise. The address must be 16-byte aligned. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_stream_ps (float *__P, __m128 __A) +{ + __builtin_ia32_movntps (__P, (__v4sf)__A); +} + +/* Guarantees that every preceding store is globally visible before + any subsequent store. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sfence (void) +{ + __builtin_ia32_sfence (); +} + +/* Transpose the 4x4 matrix composed of row[0-3]. */ +#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \ +do { \ + __v4sf __r0 = (row0), __r1 = (row1), __r2 = (row2), __r3 = (row3); \ + __v4sf __t0 = __builtin_ia32_unpcklps (__r0, __r1); \ + __v4sf __t1 = __builtin_ia32_unpcklps (__r2, __r3); \ + __v4sf __t2 = __builtin_ia32_unpckhps (__r0, __r1); \ + __v4sf __t3 = __builtin_ia32_unpckhps (__r2, __r3); \ + (row0) = __builtin_ia32_movlhps (__t0, __t1); \ + (row1) = __builtin_ia32_movhlps (__t1, __t0); \ + (row2) = __builtin_ia32_movlhps (__t2, __t3); \ + (row3) = __builtin_ia32_movhlps (__t3, __t2); \ +} while (0) + +/* For backward source compatibility. */ +# include + +#ifdef __DISABLE_SSE__ +#undef __DISABLE_SSE__ +#pragma GCC pop_options +#endif /* __DISABLE_SSE__ */ + +/* The execution of the next instruction is delayed by an implementation + specific amount of time. The instruction does not modify the + architectural state. This is after the pop_options pragma because + it does not require SSE support in the processor--the encoding is a + nop on processors that do not support it. */ +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_pause (void) +{ + __builtin_ia32_pause (); +} + +#endif /* _XMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xopintrin.h b/template/sysroot/include/xopintrin.h new file mode 100644 index 0000000..fd2892b --- /dev/null +++ b/template/sysroot/include/xopintrin.h @@ -0,0 +1,850 @@ +/* Copyright (C) 2007-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86INTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XOPMMINTRIN_H_INCLUDED +#define _XOPMMINTRIN_H_INCLUDED + +#include + +#ifndef __XOP__ +#pragma GCC push_options +#pragma GCC target("xop") +#define __DISABLE_XOP__ +#endif /* __XOP__ */ + +/* Integer multiply/add instructions. */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacssww ((__v8hi)__A,(__v8hi)__B, (__v8hi)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacsww ((__v8hi)__A, (__v8hi)__B, (__v8hi)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccsd_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacsswd ((__v8hi)__A, (__v8hi)__B, (__v4si)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccd_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacswd ((__v8hi)__A, (__v8hi)__B, (__v4si)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccs_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacssdd ((__v4si)__A, (__v4si)__B, (__v4si)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macc_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacsdd ((__v4si)__A, (__v4si)__B, (__v4si)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccslo_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacssdql ((__v4si)__A, (__v4si)__B, (__v2di)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macclo_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacsdql ((__v4si)__A, (__v4si)__B, (__v2di)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maccshi_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacssdqh ((__v4si)__A, (__v4si)__B, (__v2di)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_macchi_epi32(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmacsdqh ((__v4si)__A, (__v4si)__B, (__v2di)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddsd_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmadcsswd ((__v8hi)__A,(__v8hi)__B,(__v4si)__C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_maddd_epi16(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpmadcswd ((__v8hi)__A,(__v8hi)__B,(__v4si)__C); +} + +/* Packed Integer Horizontal Add and Subtract */ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddw_epi8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddbw ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddd_epi8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddbd ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epi8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddbq ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddd_epi16(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddwd ((__v8hi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epi16(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddwq ((__v8hi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epi32(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphadddq ((__v4si)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddw_epu8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddubw ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddd_epu8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddubd ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epu8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddubq ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddd_epu16(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphadduwd ((__v8hi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epu16(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphadduwq ((__v8hi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_haddq_epu32(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphaddudq ((__v4si)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsubw_epi8(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphsubbw ((__v16qi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsubd_epi16(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphsubwd ((__v8hi)__A); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_hsubq_epi32(__m128i __A) +{ + return (__m128i) __builtin_ia32_vphsubdq ((__v4si)__A); +} + +/* Vector conditional move and permute */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cmov_si128(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpcmov (__A, __B, __C); +} + +extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cmov_si256(__m256i __A, __m256i __B, __m256i __C) +{ + return (__m256i) __builtin_ia32_vpcmov256 (__A, __B, __C); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_perm_epi8(__m128i __A, __m128i __B, __m128i __C) +{ + return (__m128i) __builtin_ia32_vpperm ((__v16qi)__A, (__v16qi)__B, (__v16qi)__C); +} + +/* Packed Integer Rotates and Shifts + Rotates - Non-Immediate form */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rot_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vprotb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rot_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vprotw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rot_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vprotd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_rot_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vprotq ((__v2di)__A, (__v2di)__B); +} + +/* Rotates - Immediate form */ + +#ifdef __OPTIMIZE__ +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roti_epi8(__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_vprotbi ((__v16qi)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roti_epi16(__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_vprotwi ((__v8hi)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roti_epi32(__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_vprotdi ((__v4si)__A, __B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_roti_epi64(__m128i __A, const int __B) +{ + return (__m128i) __builtin_ia32_vprotqi ((__v2di)__A, __B); +} +#else +#define _mm_roti_epi8(A, N) \ + ((__m128i) __builtin_ia32_vprotbi ((__v16qi)(__m128i)(A), (int)(N))) +#define _mm_roti_epi16(A, N) \ + ((__m128i) __builtin_ia32_vprotwi ((__v8hi)(__m128i)(A), (int)(N))) +#define _mm_roti_epi32(A, N) \ + ((__m128i) __builtin_ia32_vprotdi ((__v4si)(__m128i)(A), (int)(N))) +#define _mm_roti_epi64(A, N) \ + ((__m128i) __builtin_ia32_vprotqi ((__v2di)(__m128i)(A), (int)(N))) +#endif + +/* Shifts */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shl_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshlb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shl_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshlw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shl_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshld ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shl_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshlq ((__v2di)__A, (__v2di)__B); +} + + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshab ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshaw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshad ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_sha_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpshaq ((__v2di)__A, (__v2di)__B); +} + +/* Compare and Predicate Generation + pcom (integer, unsigned bytes) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltub ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleub ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtub ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeub ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomequb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomnequb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseub ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epu8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueub ((__v16qi)__A, (__v16qi)__B); +} + +/*pcom (integer, unsigned words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltuw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleuw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtuw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeuw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomequw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomnequw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseuw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epu16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueuw ((__v8hi)__A, (__v8hi)__B); +} + +/*pcom (integer, unsigned double words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltud ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleud ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtud ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeud ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomequd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomnequd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseud ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epu32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueud ((__v4si)__A, (__v4si)__B); +} + +/*pcom (integer, unsigned quad words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltuq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleuq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtuq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeuq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomequq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomnequq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseuq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epu64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueuq ((__v2di)__A, (__v2di)__B); +} + +/*pcom (integer, signed bytes) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomeqb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomneqb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseb ((__v16qi)__A, (__v16qi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epi8(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueb ((__v16qi)__A, (__v16qi)__B); +} + +/*pcom (integer, signed words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomlew ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgew ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomeqw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomneqw ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalsew ((__v8hi)__A, (__v8hi)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epi16(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtruew ((__v8hi)__A, (__v8hi)__B); +} + +/*pcom (integer, signed double words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomled ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomged ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomeqd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomneqd ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalsed ((__v4si)__A, (__v4si)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epi32(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrued ((__v4si)__A, (__v4si)__B); +} + +/*pcom (integer, signed quad words) */ + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comlt_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomltq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comle_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomleq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comgt_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgtq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comge_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomgeq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comeq_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomeqq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comneq_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomneqq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comfalse_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomfalseq ((__v2di)__A, (__v2di)__B); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_comtrue_epi64(__m128i __A, __m128i __B) +{ + return (__m128i) __builtin_ia32_vpcomtrueq ((__v2di)__A, (__v2di)__B); +} + +/* FRCZ */ + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_frcz_ps (__m128 __A) +{ + return (__m128) __builtin_ia32_vfrczps ((__v4sf)__A); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_frcz_pd (__m128d __A) +{ + return (__m128d) __builtin_ia32_vfrczpd ((__v2df)__A); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_frcz_ss (__m128 __A, __m128 __B) +{ + return (__m128) __builtin_ia32_movss ((__v4sf)__A, + (__v4sf) + __builtin_ia32_vfrczss ((__v4sf)__B)); +} + +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_frcz_sd (__m128d __A, __m128d __B) +{ + return (__m128d) __builtin_ia32_movsd ((__v2df)__A, + (__v2df) + __builtin_ia32_vfrczsd ((__v2df)__B)); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_frcz_ps (__m256 __A) +{ + return (__m256) __builtin_ia32_vfrczps256 ((__v8sf)__A); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_frcz_pd (__m256d __A) +{ + return (__m256d) __builtin_ia32_vfrczpd256 ((__v4df)__A); +} + +/* PERMIL2 */ + +#ifdef __OPTIMIZE__ +extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permute2_pd (__m128d __X, __m128d __Y, __m128i __C, const int __I) +{ + return (__m128d) __builtin_ia32_vpermil2pd ((__v2df)__X, + (__v2df)__Y, + (__v2di)__C, + __I); +} + +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2_pd (__m256d __X, __m256d __Y, __m256i __C, const int __I) +{ + return (__m256d) __builtin_ia32_vpermil2pd256 ((__v4df)__X, + (__v4df)__Y, + (__v4di)__C, + __I); +} + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_permute2_ps (__m128 __X, __m128 __Y, __m128i __C, const int __I) +{ + return (__m128) __builtin_ia32_vpermil2ps ((__v4sf)__X, + (__v4sf)__Y, + (__v4si)__C, + __I); +} + +extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_permute2_ps (__m256 __X, __m256 __Y, __m256i __C, const int __I) +{ + return (__m256) __builtin_ia32_vpermil2ps256 ((__v8sf)__X, + (__v8sf)__Y, + (__v8si)__C, + __I); +} +#else +#define _mm_permute2_pd(X, Y, C, I) \ + ((__m128d) __builtin_ia32_vpermil2pd ((__v2df)(__m128d)(X), \ + (__v2df)(__m128d)(Y), \ + (__v2di)(__m128i)(C), \ + (int)(I))) + +#define _mm256_permute2_pd(X, Y, C, I) \ + ((__m256d) __builtin_ia32_vpermil2pd256 ((__v4df)(__m256d)(X), \ + (__v4df)(__m256d)(Y), \ + (__v4di)(__m256i)(C), \ + (int)(I))) + +#define _mm_permute2_ps(X, Y, C, I) \ + ((__m128) __builtin_ia32_vpermil2ps ((__v4sf)(__m128)(X), \ + (__v4sf)(__m128)(Y), \ + (__v4si)(__m128i)(C), \ + (int)(I))) + +#define _mm256_permute2_ps(X, Y, C, I) \ + ((__m256) __builtin_ia32_vpermil2ps256 ((__v8sf)(__m256)(X), \ + (__v8sf)(__m256)(Y), \ + (__v8si)(__m256i)(C), \ + (int)(I))) +#endif /* __OPTIMIZE__ */ + +#ifdef __DISABLE_XOP__ +#undef __DISABLE_XOP__ +#pragma GCC pop_options +#endif /* __DISABLE_XOP__ */ + +#endif /* _XOPMMINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xsavecintrin.h b/template/sysroot/include/xsavecintrin.h new file mode 100644 index 0000000..39f5c6b --- /dev/null +++ b/template/sysroot/include/xsavecintrin.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XSAVECINTRIN_H_INCLUDED +#define _XSAVECINTRIN_H_INCLUDED + +#ifndef __XSAVEC__ +#pragma GCC push_options +#pragma GCC target("xsavec") +#define __DISABLE_XSAVEC__ +#endif /* __XSAVEC__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsavec (void *__P, long long __M) +{ + __builtin_ia32_xsavec (__P, __M); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsavec64 (void *__P, long long __M) +{ + __builtin_ia32_xsavec64 (__P, __M); +} +#endif + +#ifdef __DISABLE_XSAVEC__ +#undef __DISABLE_XSAVEC__ +#pragma GCC pop_options +#endif /* __DISABLE_XSAVEC__ */ + +#endif /* _XSAVECINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xsaveintrin.h b/template/sysroot/include/xsaveintrin.h new file mode 100644 index 0000000..88ecbef --- /dev/null +++ b/template/sysroot/include/xsaveintrin.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XSAVEINTRIN_H_INCLUDED +#define _XSAVEINTRIN_H_INCLUDED + +#ifndef __XSAVE__ +#pragma GCC push_options +#pragma GCC target("xsave") +#define __DISABLE_XSAVE__ +#endif /* __XSAVE__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsave (void *__P, long long __M) +{ + __builtin_ia32_xsave (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstor (void *__P, long long __M) +{ + __builtin_ia32_xrstor (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsetbv (unsigned int __A, long long __V) +{ + __builtin_ia32_xsetbv (__A, __V); +} + +extern __inline long long +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xgetbv (unsigned int __A) +{ + return __builtin_ia32_xgetbv (__A); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsave64 (void *__P, long long __M) +{ + __builtin_ia32_xsave64 (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstor64 (void *__P, long long __M) +{ + __builtin_ia32_xrstor64 (__P, __M); +} +#endif + +#ifdef __DISABLE_XSAVE__ +#undef __DISABLE_XSAVE__ +#pragma GCC pop_options +#endif /* __DISABLE_XSAVE__ */ + +#endif /* _XSAVEINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xsaveoptintrin.h b/template/sysroot/include/xsaveoptintrin.h new file mode 100644 index 0000000..657da5d --- /dev/null +++ b/template/sysroot/include/xsaveoptintrin.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XSAVEOPTINTRIN_H_INCLUDED +#define _XSAVEOPTINTRIN_H_INCLUDED + +#ifndef __XSAVEOPT__ +#pragma GCC push_options +#pragma GCC target("xsaveopt") +#define __DISABLE_XSAVEOPT__ +#endif /* __XSAVEOPT__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaveopt (void *__P, long long __M) +{ + __builtin_ia32_xsaveopt (__P, __M); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaveopt64 (void *__P, long long __M) +{ + __builtin_ia32_xsaveopt64 (__P, __M); +} +#endif + +#ifdef __DISABLE_XSAVEOPT__ +#undef __DISABLE_XSAVEOPT__ +#pragma GCC pop_options +#endif /* __DISABLE_XSAVEOPT__ */ + +#endif /* _XSAVEOPTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xsavesintrin.h b/template/sysroot/include/xsavesintrin.h new file mode 100644 index 0000000..88cdebb --- /dev/null +++ b/template/sysroot/include/xsavesintrin.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2014-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XSAVESINTRIN_H_INCLUDED +#define _XSAVESINTRIN_H_INCLUDED + +#ifndef __XSAVES__ +#pragma GCC push_options +#pragma GCC target("xsaves") +#define __DISABLE_XSAVES__ +#endif /* __XSAVES__ */ + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaves (void *__P, long long __M) +{ + __builtin_ia32_xsaves (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstors (void *__P, long long __M) +{ + __builtin_ia32_xrstors (__P, __M); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstors64 (void *__P, long long __M) +{ + __builtin_ia32_xrstors64 (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaves64 (void *__P, long long __M) +{ + __builtin_ia32_xsaves64 (__P, __M); +} +#endif + +#ifdef __DISABLE_XSAVES__ +#undef __DISABLE_XSAVES__ +#pragma GCC pop_options +#endif /* __DISABLE_XSAVES__ */ + +#endif /* _XSAVESINTRIN_H_INCLUDED */ diff --git a/template/sysroot/include/xtestintrin.h b/template/sysroot/include/xtestintrin.h new file mode 100644 index 0000000..af4cb8b --- /dev/null +++ b/template/sysroot/include/xtestintrin.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2012-2024 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _X86GPRINTRIN_H_INCLUDED +# error "Never use directly; include instead." +#endif + +#ifndef _XTESTINTRIN_H_INCLUDED +#define _XTESTINTRIN_H_INCLUDED + +#ifndef __RTM__ +#pragma GCC push_options +#pragma GCC target("rtm") +#define __DISABLE_RTM__ +#endif /* __RTM__ */ + +/* Return non-zero if the instruction executes inside an RTM or HLE code + region. Return zero otherwise. */ +extern __inline int +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xtest (void) +{ + return __builtin_ia32_xtest (); +} + +#ifdef __DISABLE_RTM__ +#undef __DISABLE_RTM__ +#pragma GCC pop_options +#endif /* __DISABLE_RTM__ */ + +#endif /* _XTESTINTRIN_H_INCLUDED */ diff --git a/template/sysroot/lib/libbearssl.a b/template/sysroot/lib/libbearssl.a new file mode 100644 index 0000000000000000000000000000000000000000..40537c53f614e9c4e6fc7379798e3de67bd71dc4 GIT binary patch literal 958944 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